tenth_认证_限流_各种功能_自动生成文档接口_xadmin功能使用
# 配置文件里的代码集合 REST_FRAMEWORK = { # 全局配置的认证 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', # session认证 'rest_framework.authentication.BasicAuthentication', # 基本认证 ), # 全局配置的权限识别 'DEFAULT_PERMISSION_CLASSES': ( # IsAuthenticated 表示只有登录过的用户才能访问 'rest_framework.permissions.AllowAny', ), # 限流[全局] 'DEFAULT_THROTTLE_CLASSES': ( 'rest_framework.throttling.AnonRateThrottle', # 匿名用户,游客 'rest_framework.throttling.UserRateThrottle' # 已经经过认证的用户 ), 'DEFAULT_THROTTLE_RATES': { 'anon': '5/minute', 'user': '10/minute' }, # 过滤 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',), # 全局分页[一旦设置了全局分页,所以给予rest_framework的视图扩展类里面的list方法提供的列表页api接口都会产生分页效果] # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 'PAGE_SIZE': 3 # 每页数目 # 自定义异常处理 'EXCEPTION_HANDLER': 'drfdemo.exceptions.custom_exception_handler', }
2. 认证Authentication
# settings里配置全局认证方案 REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', # session认证 'rest_framework.authentication.BasicAuthentication', # 基本认证 ) } # 也可以在每个视图中设置authentication_classes属性来设置 from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.views import APIView class ExampleView(APIView): # 类属性 authentication_classes = [SessionAuthentication, BasicAuthentication] ... 认证失败会有两种可能的返回值: - 401 Unauthorized 未认证 - 403 Permission Denied 权限被禁止
3. 权限Permissions
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。
-
在执行视图的dispatch()方法前,会先进行视图访问权限的判断
-
在通过get_object()获取具体对象时,会进行模型对象访问权限的判断
# 配置文件中全局设置默认的权限管理类,如 REST_FRAMEWORK = { .... 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) } # 如果未指明,则采用如下默认配置 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny', ) # 也可以在具体的视图通过permission_classes属性来设置,如 from rest_framework.permissions import IsAuthenticated from rest_framework.views import APIView class ExampleView(APIView): permission_classes = (IsAuthenticated,) ...
提供的权限
-
AllowAny 允许所有用户
-
IsAuthenticated 仅通过认证的用户
-
-
IsAuthenticatedOrReadOnly 已经登陆认证的用户可以对数据进行增删改操作,没有登陆认证的只能查看数据
# 如 from rest_framework.authentication import SessionAuthentication from rest_framework.permissions import IsAuthenticated from rest_framework.generics import RetrieveAPIView class StudentAPIView(RetrieveAPIView): queryset = Student.objects.all() serializer_class = StudentSerializer authentication_classes = [SessionAuthentication] permission_classes = [IsAuthenticated] # 自定义权限,rest_framework.permissions.BasePermission父类, # 并实现以下两个任何一个方法或全部 - .has_permission(self, request, view)` 是否可以访问视图, view表示当前视图对象 - .has_object_permission(self, request, view, obj)` 是否可以访问数据对象, view表示当前视图, obj为数据对象 # 如,在当前子应用下,创建一个权限文件permission.py 中声明自定义权限类 from rest_framework.permissions import BasePermission class IsXiaoMingPermission(BasePermission): def has_permission(self, request, view): if( request.user.username == "xiaoming" ): return True from .permissions import IsXiaoMingPermission class StudentViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentSerializer permission_classes = [IsXiaoMingPermission]
4. 限流Throttling
可以对接口访问的频次进行限制,以减轻服务器压力。
# 使用,可以在配置文件中,使用`DEFAULT_THROTTLE_CLASSES` 和 `DEFAULT_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`, `hour` 或`day`来指明周期。 # 也可以在具体视图中通过throttle_classess属性来配置,如 from rest_framework.throttling import UserRateThrottle from rest_framework.views import APIView class ExampleView(APIView): throttle_classes = (UserRateThrottle,) ...
可选限流类
1) AnonRateThrottle
限制所有匿名未认证用户,使用IP区分用户。
使用DEFAULT_THROTTLE_RATES['anon'] 来设置频次
2)UserRateThrottle
限制认证用户,使用User id 来区分。
使用DEFAULT_THROTTLE_RATES['user'] 来设置频次
3)ScopedRateThrottle
class ContactListView(APIView): throttle_scope = 'contacts' ... class ContactDetailView(APIView): throttle_scope = 'contacts' ... class UploadView(APIView): throttle_scope = 'uploads' ... REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': ( 'rest_framework.throttling.ScopedRateThrottle', ), 'DEFAULT_THROTTLE_RATES': { 'contacts': '1000/day', 'uploads': '20/day' } } # 全局配置中设置访问频率 'DEFAULT_THROTTLE_RATES': { 'anon': '3/minute', 'user': '10/minute' }
5. 过滤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 = StudentSerializer filter_fields = ('age', 'sex') # 127.0.0.1:8000/four/students/?sex=1
6. 排序
对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。
使用方法:
在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
# 例子 class StudentListView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer filter_backends = [OrderingFilter] ordering_fields = ('id', 'age') # 127.0.0.1:8000/books/?ordering=-age # -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 = StudentModelSerializer filter_fields = ('age', 'sex') # 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明, # 否则过滤功能会失效 filter_backends = [OrderingFilter,DjangoFilterBackend] ordering_fields = ('id', 'age')
7. 分页Pagination
# REST framework提供了分页的支持。 # 我们可以在配置文件中设置全局的分页方式,如: REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 100 # 每页数目 } # 也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas属性来指明。 class LargeResultsSetPagination(PageNumberPagination): page_size = 1000 page_size_query_param = 'page_size' max_page_size = 10000 class BookDetailView(RetrieveAPIView): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer pagination_class = LargeResultsSetPagination # 注意:如果在视图内关闭分页功能,只需在视图内设置 pagination_class = None
# 可选分页器 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 = StudentModelSerializer pagination_class = StandardPageNumberPagination # 127.0.0.1/four/students/?p=1&size=5 # LimitOffsetPagination GET http://127.0.0.1/four/students/?limit=100&offset=400 可以在子类中定义的属性: - 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_size default_limit = 2 limit_query_param = "size" offset_query_param = "start" class StudentAPIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer # 调用页码分页类 # pagination_class = StandardPageNumberPagination # 调用查询偏移分页类 pagination_class = StandardLimitOffsetPagination
8. 异常处理 Exceptions
# REST framework提供了异常处理,我们可以自定义异常处理函数及新建一个异常处理文件。
from rest_framework.views import exception_handler def custom_exception_handler(exc, context): # 先调用REST framework默认的异常处理方法获得标准错误响应对象 response = exception_handler(exc, context) # 在此处补充自定义的异常处理 if response is None: response.data['status_code'] = response.status_code return 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' }
REST framework定义的异常
-
APIException 所有异常的父类
-
ParseError 解析错误
-
AuthenticationFailed 认证失败
-
NotAuthenticated 尚未认证
-
PermissionDenied 权限决绝
-
NotFound 未找到
-
MethodNotAllowed 请求方式不支持
-
NotAcceptable 要获取的数据格式不支持
-
Throttled 超过限流次数
-
ValidationError 校验失败
也就是说,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。
9. 自动生成接口文档
REST framework可以自动帮助我们生成接口文档。
接口文档以网页的方式呈现。
自动接口文档能生成的是继承自APIView及其子类的视图。
# 安装依赖 REST framewrok生成接口文档需要`coreapi`库的支持。 pip install coreapi # 设置接口文档访问路径 # 在总路由中添加接口文档路径,文档路由对应的视图配置为。 # rest_framework.documentation.include_docs_urls,参数`title`为接口文档网站的标题。 from rest_framework.documentation import include_docs_urls urlpatterns = [ ... path('docs/', include_docs_urls(title='站点页面标题')) ] # 文档描述说明的定义位置 # 1) 单一方法的视图,可直接使用类视图的文档字符串,如 class BookListView(generics.ListAPIView): """ 返回所有图书信息. """ # 2)包含多个方法的视图,在类视图的文档字符串中,分开方法定义,如 class BookListCreateView(generics.ListCreateAPIView): """ get: 返回所有图书信息. post: 新建图书. """ # 3)对于视图集ViewSet,仍在类视图的文档字符串中封开定义,但是应使用action名称区分,如 class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet): """ list: 返回图书列表数据 retrieve: 返回图书详情数据 latest: 返回最新的图书数据 read: 修改图书的阅读量 # 访问接口文档网页 # 浏览器访问 127.0.0.1:8000/docs/,即可看到自动生成的接口文档。
10. Xadmin
xadmin是Django的第三方扩展,比使用Django的admin站点更强大也更方便。
# 通过如下命令安装xadmin的最新版 pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2 # 在配置文件中注册如下应用 INSTALLED_APPS = [ ... 'xadmin', 'crispy_forms', 'reversion', ... ] # 修改使用中文界面 LANGUAGE_CODE = 'zh-Hans' # 修改时区 TIME_ZONE = 'Asia/Shanghai' # xadmin有建立自己的数据库模型类,需要进行数据库迁移 python manage.py makemigrations python manage.py migrate # 在总路由中添加xadmin的路由信息 import xadmin xadmin.autodiscover() # version模块自动注册需要版本控制的 Model from xadmin.plugins import xversion xversion.register_models() urlpatterns = [ path(r'xadmin/', xadmin.site.urls), ] # 如果之前没有创建超级用户,需要创建,如果有了,则可以直接使用之前的。 python manage.py createsuperuser
# 使用 - xadmin不再使用Django的admin.py,而是需要编写代码在adminx.py文件中。 - xadmin的站点管理类不用继承`admin.ModelAdmin`,而是直接继承`object`即可。 例如:在子应用中创建adminx.py文件。 # 站点的全局配置 import xadmin from xadmin import views class BaseSetting(object): """xadmin的基本配置""" enable_themes = True # 开启主题切换功能 use_bootswatch = True xadmin.site.register(views.BaseAdminView, BaseSetting) class GlobalSettings(object): """xadmin的全局配置""" site_title = "路飞学城" # 设置站点标题 site_footer = "路飞学城有限公司" # 设置站点的页脚 menu_style = "accordion" # 设置菜单折叠 # 站点Model 管理 xadmin可以使用的页面样式控制基本与Django原生的admin一直。 - **list_display** 控制列表展示的字段 ``` list_display = ['id', 'btitle', 'bread', 'bcomment'] ``` - **search_fields** 控制可以通过搜索框搜索的字段名称,xadmin使用的是模糊查询 ``` search_fields = ['id','btitle'] ``` - **list_filter** 可以进行过滤操作的列,对于分类、性别、状态 ``` list_filter = ['is_delete'] ``` - **ordering** 默认排序的字段 - **show_detail_fields** 在列表页提供快速显示详情信息 - **list_editable** 在列表页可以快速直接编辑的字段 - **refresh_times** 指定列表页的定时刷新 ``` refresh_times = [5, 10,30,60] # 设置允许后端管理人员按多长时间(秒)刷新页面 ``` - **list_export** 控制列表页导出数据的可选格式 ``` list_export = ('xls', 'xml', 'json') list_export设置为None来禁用数据导出功能 list_export_fields = ('id', 'btitle', 'bpub_date') ``` - **show_bookmarks** 控制是否显示书签功能 ``` show_bookmarks = True ``` - **data_charts** 控制显示图表的样式 ```python data_charts = { "order_amount": { 'title': '图书发布日期表', "x-field": "bpub_date", "y-field": ('btitle',), "order": ('id',) }, # 支持生成多个不同的图表 # "order_amount": { # 'title': '图书发布日期表', # "x-field": "bpub_date", # "y-field": ('btitle',), # "order": ('id',) # }, } ``` - title 控制图标名称 - x-field 控制x轴字段 - y-field 控制y轴字段,可以是多个值 - order 控制默认排序 - **model_icon** 控制菜单的图标【图标的设置可以参考bootstrap的图标css名称】 ``` class BookInfoAdmin(object): model_icon = 'fa fa-gift' xadmin.site.register(models.BookInfo, BookInfodmin) ``` - **readonly_fields** 在编辑页面的只读字段 - **exclude** 在编辑页面隐藏的字段 xadmin.site.register(views.CommAdminView, GlobalSettings)
11. 关于cors 跨域的另一种方法
# 按照依赖包 pip install django-cors-headers # 在全局settings配置 INSTALLED_APPS = [ ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middelware.CorsMiddleware', # 必须在第一位 ... ] # 配置可互通域名,也是settings 里 CORS_ORIGIN_WHITELIST = ( '127.0.0.1:8000', # 我的请求前端 '127.0.0.1:8080', # 我的响应后端 ... )