【django2.0之Rest_Framework框架三】rest_framework认证,权限,限流,过滤,排序,分页,异常处理,生成文档介绍

本文主要是介绍【django2.0之Rest_Framework框架三】rest_framework认证,权限,限流,过滤,排序,分页,异常处理,生成文档介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 认证Authentication

  1. 全局配置
    可以在配置文件中配置全局默认的认证方案。
from rest_framework import settings# 在settings配置文件中,我们可以进行下面的配置来覆盖默认配置
REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': (#哪个写在前面,优先使用哪个认证'rest_framework.authentication.SessionAuthentication',  # session认证,admin后台其实就使用的session认证,其实接口开发很少用到session认证,所以我们通过配置可以改为其他认证,比如后面项目里面我们用到jwt,JSON WEB TOKEN认证,或者一些配合redis的认证'rest_framework.authentication.BasicAuthentication',   # 基本认证,工作当中可能一些测试人员会参与的话,他们会将一些认证数据保存在内存当中,然后验证的,我们基本上用不上)
}
  1. 局部使用
    也可以在每个视图中通过设置authentication_classess属性来设置,比如说我们很多接口的数据都是可以让别人获取数据的,但是有可能有些接口是调用给别人网站的,有可能到时候我们就需要一些单独的认证了
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIViewclass ExampleView(APIView):# 类属性authentication_classes = [SessionAuthentication, BasicAuthentication] #也可以写成元祖形式的,到时候我们使用我们自己开发的认证组件的时候,就需要自己写一个认证组件类,然后写在列表中来使用...

认证失败会有两种可能的返回值:

  • 401 Unauthorized 未认证
  • 403 Permission Denied 权限被禁止

自定义认证组件

## 写一个认证类 students/utils/app_auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from students.models import UserToken
class MyAuthentication(BaseAuthentication):def authenticate(self, request):# 认证逻辑,如果认证通过,返回两个值#如果认证失败,抛出AuthenticationFailed异常token=request.GET.get('token')if  token:user_token=UserToken.objects.filter(token=token).first()# 认证通过if user_token:return user_token.user,tokenelse:raise AuthenticationFailed('认证失败')else:raise AuthenticationFailed('请求地址中需要携带token')# 可以有多个认证,从左到右依次执行
# 全局使用,在setting.py中配置
REST_FRAMEWORK={"DEFAULT_AUTHENTICATION_CLASSES":["students.utils.app_auth.MyAuthentication",]
}
# 局部使用,在视图类上写
## views.py
from students.utils.app_auth import MyAuthentication
class StudentView(APIView):authentication_classes = [MyAuthentication, ]def get(self,request):print(request.user)  # 用户名print(request.auth)  # tokenreturn Response({'msg':'ok'})
# 局部禁用
authentication_classes=[]

2. 权限Permissions

权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

  • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
  • 在通过get_object()获取具体对象时,会进行模型对象访问权限的判断
  1. 全局使用
    可以在配置文件中全局设置默认的权限管理类,如
REST_FRAMEWORK = {....'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated', #登录状态下才能访问我们的接口,可以通过退出admin后台之后,你看一下还能不能访问我们正常的接口就看到效果了)
}

如果未指明,则采用如下默认配置

from rest_framework import permissions
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny', #表示任何人都可以进行任何的操作,没做限制
)
  1. 局部使用
    也可以在具体的视图中通过permission_classes属性来设置,如
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIViewclass ExampleView(APIView):permission_classes = (IsAuthenticated,)...

内置提供的权限

  • AllowAny 允许所有用户
  • IsAuthenticated 仅通过认证的用户

自定义权限的使用

如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并重写has_permission(self, request, view) 方法表示是否可以访问视图, view表示当前视图对象。如果权限通过,就返回True,不通过就返回False

## utils/permissions.py
from rest_framework.permissions import BasePermissionclass UserPermission(BasePermission):def  has_permission(self, request, view):# 不是超级用户,不能访问# 由于认证已经过了,request内就有user对象了,当前登录用户user=request.user  # 当前登录用户# 如果该字段用了choice,通过get_字段名_display()就能取出choice后面的中文print(user.get_user_type_display())if user.user_type==1:return Trueelse:return False# 局部使用
## views.py
class TestView(APIView):permission_classes = [permissions.UserPermission]def get(self,request):return Response({'msg':'ok'})
# 全局使用
REST_FRAMEWORK={"DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",],'DEFAULT_PERMISSION_CLASSES': ['app01.app_auth.UserPermission',],
}
# 局部禁用
class TestView(APIView):permission_classes = []

3. 限流Throttling

可以对接口访问的频次进行限制,以减轻服务器压力。
一般用于付费购买次数,投票等场景使用.

  1. 全局使用
    可以在配置文件中,使用DEFAULT_THROTTLE_CLASSESDEFAULT_THROTTLE_RATES进行全局配置
REST_FRAMEWORK = {'DEFAULT_THROTTLE_CLASSES': ('rest_framework.throttling.AnonRateThrottle', # 匿名用户,未登录的'rest_framework.throttling.UserRateThrottle'  # 经过登录之后的用户),'DEFAULT_THROTTLE_RATES': {'anon': '100/day','user': '1000/day'}
}

DEFAULT_THROTTLE_RATES 可以使用 second, minute, hourday来指明周期。

源码:
{'s': 1, 'm': 60, 'h': 3600, 'd': 86400} m表示分钟,可以写m,也可以写minute
  1. 局部使用
    也可以在具体视图中通过throttle_classess属性来配置
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIViewclass ExampleView(APIView):throttle_classes = (UserRateThrottle,)...

内置频率组件源码

from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
import time
from rest_framework import exceptions
visit_record = {}
class VisitThrottle(BaseThrottle):# 限制访问时间VISIT_TIME = 10VISIT_COUNT = 3# 定义方法 方法名和参数不能变def allow_request(self, request, view):# 获取登录主机的idid = request.META.get('REMOTE_ADDR')self.now = time.time()if id not in visit_record:visit_record[id] = []self.history = visit_record[id]# 限制访问时间while self.history and self.now - self.history[-1] > self.VISIT_TIME:self.history.pop()# 此时 history中只保存了最近10秒钟的访问记录if len(self.history) >= self.VISIT_COUNT:return Falseelse:self.history.insert(0, self.now)return Truedef wait(self):return self.history[-1] + self.VISIT_TIME - self.now

可选限流类

1) AnonRateThrottle
限制所有匿名未认证用户,使用IP区分用户。
使用DEFAULT_THROTTLE_RATES['anon'] 来设置频次

2)UserRateThrottle
限制认证用户,使用User id 来区分。
使用DEFAULT_THROTTLE_RATES['user'] 来设置频次

示例

全局配置中设置访问频率

	'DEFAULT_THROTTLE_CLASSES': ('rest_framework.throttling.AnonRateThrottle','rest_framework.throttling.UserRateThrottle'),'DEFAULT_THROTTLE_RATES': {'anon': '3/m','user': '10/m'}

4. 过滤Filtering

对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。

pip install django-filter

在配置文件中增加过滤后端的设置:

INSTALLED_APPS = [...'django_filters',  # 需要注册应用,
]
# 全局配置
REST_FRAMEWORK = {...'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}

在视图中添加filter_fields属性,指定可以过滤的字段

class StudentListView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentSerializerfilter_fields = ('age', 'sex') # 配置可以按照哪个字段来过滤# 127.0.0.1:8000/stu/students/?sex=1

5. 排序Ordering

对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

使用方法:

在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。

示例:

from rest_framework.filters import OrderingFilter
class Students7View(ModelViewSet):queryset = models.Student.objects.all()  # 必须写这个参数 ,方法中使用的self.get_queryset()方法自动获取到queryset属性数据serializer_class = StudentModelSerializer  # 非必填属性,self.get_serializer获取到serializer_class制定的序列化器类filter_backends = (OrderingFilter,)ordering_fields = ('id', 'age')# students/?ordering=-id# 127.0.0.1:8000/books/?ordering=-age 
# 必须是ordering=某个值
# -id 表示针对id字段进行倒序排序
# id  表示针对id字段进行升序排序

如果需要在过滤以后再次进行排序,则需要两者结合!

from rest_framework.generics import ListAPIView
from students.models import Student
from .serializers import StudentModelSerializer
from django_filters.rest_framework import DjangoFilterBackend #需要使用一下它才能结合使用
class Student3ListView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentModelSerializerfilter_fields = ('age', 'sex')# 因为filter_backends是局部过滤配置,局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明,# 否则过滤功能会失效filter_backends = [OrderingFilter,DjangoFilterBackend]ordering_fields = ('id', 'age')# 127.0.0.1:8000/books/?sex=1&ordering=-age 

6. 分页Pagination

REST framework提供了分页的支持。
我们可以在配置文件中设置全局的分页方式,如:

REST_FRAMEWORK = {# 全局分页,一旦设置了全局分页,那么我们drf中的视图扩展类里面的list方法提供的列表页都会产生分页的效果。所以一般不用全局分页'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination','PAGE_SIZE': 100  # 每页最大数据量
}

也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_class属性来指明。

class LargeResultsSetPagination(PageNumberPagination):page_size = 1000#127.0.0.1:8001/students/?page=5&page_size=10page_size_query_param = 'page_size'max_page_size = 10000
class BookDetailView(RetrieveAPIView):queryset = BookInfo.objects.all()serializer_class = BookInfoSerializerpagination_class = LargeResultsSetPagination# pagination_class = None

注意:如果在视图内关闭分页功能,只需在视图内设置

pagination_class = None

可选分页器

1) PageNumberPagination
前端访问地址形式:

GET  http://127.0.0.1:8000/students/?page=4

可以在子类中定义的属性:

  • page_size 每页数目
  • page_query_param 前端发送的页数关键字名,默认为"page"
  • page_size_query_param 前端发送的每页数目关键字名,默认为None
  • max_page_size 前端最多能设置的每页数量
# 声明分页的配置类
from rest_framework.pagination import PageNumberPagination
class StandardPageNumberPagination(PageNumberPagination):# 默认每一页显示的数据量page_size = 2# 允许客户端通过get参数来控制每一页的数据量page_size_query_param = "size"max_page_size = 10# 自定义页码的参数名page_query_param = "p"class StudentAPIView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentModelSerializerpagination_class = StandardPageNumberPagination# 127.0.0.1/four/students/?p=1&size=5

2)LimitOffsetPagination(了解)

前端访问网址形式:其实就是通过偏移量来取数据

GET http://127.0.0.1/four/students/?limit=100&offset=400  #从下标为400的记录开始,取100条记录

可以在子类中定义的属性:

  • default_limit 默认限制,每页数据量大小,默认值与PAGE_SIZE设置一致
  • limit_query_param limit参数名,默认'limit' , 可以通过这个参数来改名字
  • offset_query_param offset参数名,默认'offset' ,可以通过这个参数来改名字
  • max_limit 最大limit限制,默认None, 无限制
from rest_framework.pagination import LimitOffsetPagination
class StandardLimitOffsetPagination(LimitOffsetPagination):# 默认每一页查询的数据量,类似上面的page_sizedefault_limit = 2limit_query_param = "size"offset_query_param = "start"class StudentAPIView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentModelSerializer# 调用页码分页类# pagination_class = StandardPageNumberPagination# 调用查询偏移分页类pagination_class = StandardLimitOffsetPagination

7. 异常处理 Exceptions

看一个简单的示例

class APIError(Exception):passclass Student2APIView(APIView):def get(self,request,pk):try:instance = Student.objects.get(pk=pk)except Student.DoesNotExist:raise APIError('自定义API错误')return Response({"message":"访问的商品已经下架~"})serializer = StudentModelSerializer(instance=instance)return Response(serializer.data)

REST framework提供了异常处理,我们可以自定义异常处理函数。

可以创建一个utils文件夹,里面放一个exceptions.py文件,名字随便写,然后写下面的内容

from rest_framework.views import exception_handlerdef custom_exception_handler(exc, context): #自定义的错误处理函数"""exc错误对象context 异常发生时的一些上下文信息"""# 先调用REST framework默认的异常处理方法获得标准错误响应对象response = exception_handler(exc, context) #这个函数是drf提供的,它处理了一些错误,但是如果它处理不了的,它会返回None,所以,如果是None的话,我们需要自己来处理错误# 在此处补充自定义的异常处理if response is None:if isinstance(exc,APIError)#这里就可以记录错误信息了,一般记录到文件中,可以使用日志系统来进行记录# return Respose({'msg':'自定义API错误了'})response.data['status_code'] = response.status_codereturn response

在配置文件中还要声明自定义的异常处理

REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}

如果未声明,会采用默认的方式,如下

## rest_frame/settings.py
REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}

例如:补充上处理关于数据库的异常

from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework import status
from django.db import DatabaseErrordef exception_handler(exc, context):response = drf_exception_handler(exc, context)if response is None:view = context['view'] #出错的方法或者函数名称if isinstance(exc, DatabaseError):print('[%s]: %s' % (view, exc))response = Response({'detail': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)return response

REST framework定义的异常

  • APIException 所有异常的父类
  • ParseError 解析错误
  • AuthenticationFailed 认证失败
  • NotAuthenticated 尚未认证
  • PermissionDenied 权限决绝
  • NotFound 未找到
  • MethodNotAllowed 请求方式不支持
  • NotAcceptable 要获取的数据格式不支持
  • Throttled 超过限流次数
  • ValidationError 校验失败

也就是说,上面列出来的异常不需要我们自行处理了,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。

8. 自动生成接口文档

REST framework可以自动帮助我们生成接口文档。
接口文档以网页的方式呈现。
自动接口文档能生成的是继承自APIView及其子类的视图。
文档:https://www.kernel.org/doc/html/v4.12/core-api/index.html

8.1. 安装依赖

REST framewrok生成接口文档需要coreapi库的支持。

pip install coreapi

8.2. 设置接口文档访问路径

在总路由中添加接口文档路径。
文档路由对应的视图配置为rest_framework.documentation.include_docs_urls
参数title为接口文档网站的标题。

from rest_framework.documentation import include_docs_urlsurlpatterns = [...path('docs/', include_docs_urls(title='站点页面标题'))
]

如果报错了下面的错误,说明我们缺少一个依赖,配置一下就行了
'AutoSchema' object has no attribute 'get_link'
配置:

REST_FRAMEWORK = {...'DEFAULT_SCHEMA_CLASS': "rest_framework.schemas.AutoSchema",}

8.3. 文档描述说明的定义位置

1) 单一方法的视图,可直接使用类视图的文档字符串,如

class BookListView(generics.ListAPIView):"""get: 返回所有图书信息.post: 添加记录"""#注意,这是在类中声明的注释,如果在方法中你声明了其他注释,会覆盖这个注释的

2)包含多个方法的视图,在类视图的文档字符串中,分开方法定义,如

class BookListCreateView(generics.ListCreateAPIView):"""get:返回所有图书信息.post:新建图书."""

3)对于视图集ViewSet,仍在类视图的文档字符串中封开定义,但是应使用action名称区分,如

class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):"""list:返回图书列表数据retrieve:返回图书详情数据latest:返回最新的图书数据read:修改图书的阅读量"""

8.4. 访问接口文档网页

浏览器访问 127.0.0.1:8000/docs/,即可看到自动生成的接口文档。

两点说明:

1) 视图集ViewSet中的retrieve名称,在接口文档网站中叫做read
2)参数的Description需要在模型类或序列化器类的字段中以help_text选项定义,如:

class Student(models.Model):...age = models.IntegerField(default=0, verbose_name='年龄', help_text='年龄')...

或 注意,如果你多个应用使用同一个序列化器,可能会导致help_text的内容显示有些问题,小事情

class StudentSerializer(serializers.ModelSerializer):class Meta:model = Studentfields = "__all__"extra_kwargs = {'age': {'required': True,'help_text': '年龄'}}

这篇关于【django2.0之Rest_Framework框架三】rest_framework认证,权限,限流,过滤,排序,分页,异常处理,生成文档介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/237024

相关文章

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

Java Response返回值的最佳处理方案

《JavaResponse返回值的最佳处理方案》在开发Web应用程序时,我们经常需要通过HTTP请求从服务器获取响应数据,这些数据可以是JSON、XML、甚至是文件,本篇文章将详细解析Java中处理... 目录摘要概述核心问题:关键技术点:源码解析示例 1:使用HttpURLConnection获取Resp