当前位置:   article > 正文

Django之DRF框架学习(Django REST framework)——其他功能(认证、权限、限流、过滤、排序、分页、异常处理、生成接口文档)_drf 'searchfilter' object has no attribute 'has_pe

drf 'searchfilter' object has no attribute 'has_permission

DRF之认证、权限、限流、过滤、排序、分页、异常处理、生成接口文档

认证

  1. 全局认证
    在配置文件中配置全局默认的认证方案
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES':(
        'rest_framework.authentication.BasicAuthentication',   # 基本认证
        'rest_framework.authentication.SessionAuthentication', # session认证
    )
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 局部认证
    在每个视图中通过设置authentication_classess属性来设置
from rest_framework.authentication import SessionAuthentication, BasicAuthentication

class BookInfo(APIView):
	authentication_classess = (SessionAuthentication, BasicAuthentication)
  • 1
  • 2
  • 3
  • 4
  1. 认证失败的返回值
  • 401 Unauthorized 未认证
  • 403 Permission Denied 权限被禁止

权限

  • 提供的权限
    1.AllowAny 允许所有用户
    2.IsAuthenticated 仅通过认证的用户
    3.IsAdminUser 仅管理员用户
    4.IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取

    例子:

配置文件为上面全局认证的配置信息

具体的视图如下:

from rest_framework.response import Response

from booktest.models import BookInfo,HeroInfo
from .serializers import BookInfoModelSerializer
# 认证需要的库
from rest_framework.viewsets import ViewSet,GenericViewSet,ReadOnlyModelViewSet,ModelViewSet

from rest_framework.decorators import action  # 自定义视图的路由
from rest_framework.permissions import IsAdminUser,AllowAny,IsAuthenticated,IsAuthenticatedOrReadOnly

class BookViewSet( ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class =  BookInfoModelSerializer
    permission_classes = [IsAuthenticated]  # 只有通过认证的用户
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

假如没通过认证的用户访问api时,出现如下:
在这里插入图片描述
这里选择的认证条件为:

permission_classes = [IsAuthenticated] # 只有通过认证的用户

  • 自定义权限
    如果需要自定义权限,需要继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部
  1. .has_permission(self, request, view)
    是否可以访问视图,view表示当前视图对象
  2. .has_object_permission(self, request, view, obj)
    是否可以访问数据对象, view表示当前视图,obj为数据对象例如:
    class MyPermission(BasePermission):
    	def has_object_permission(self, request, view, obj):
    		'''控制obj对象的访问权限,此案例拒绝所有对对象的访问'''
    		return False
    class BookInfoViewSet(ModelViewSet):
    	queryset = BookInfo.objects.all()
    	serializer_class = BookInfoSerializer
    	permission_classes = [IsAuthenticated, MyPermission]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

限流Throttling

可以对接口访问的频次进行限制,以减轻服务器压力。

  • 全局的配置
REST_FRAMEWORK = {
   ...
    'DEFAULT_THROTTLE_CLASSES':( # 限流配置
        'rest_framework.throttling.AnonRateThrottle',   # 匿名用户
        'rest_framework.throttling.UserRateThrottle',   # 登录用户
    ),
    'DEFAULT_THROTTLE_RATES':{ # 限流频次
        'anon':'10/day',  # 匿名频次
        'user':'15/day'  # 登录用户频次
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以在配置文件中,使用DEFAULT_THROTTLE_CLASSES 和 DEFAULT_THROTTLE_RATES 进行全局配置
DEFAULT_THROTTLE_RATES 可以使用 second,minute,hour,day等来指定周期
也可以在具体视图中通过throttle_classess属性来配置

from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView

class BookInfoView(APIView):
	throttle_classes = (UserRateThrottle,)
	...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 可选限流类
    1)AnonRateThrottle
    限制所有匿名未认证用户,使用IP区分用户
    使用 DEFAULT_THROTTLE_RATES[‘anon’] 来设置频次
    2)UserRateThrottle
    限制认证用户, 使用 User id 来区分
    使用 DEFAULT_THROTTLE_RATES[‘user’] 来设置频次
    3)ScopedRateTHrottle
    限制用户对于每个视图的访问频次,使用id或者user id.
    例如
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES':( # 限流配置
        'rest_framework.throttling.ScopedRateThrottle',  #自定义限制
    ),
    'DEFAULT_THROTTLE_RATES':{ # 限流频次
        'seven': '7/day'  #指定的视图访问次数限流
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在视图中指定自定的限流

class HeroViewSet( ModelViewSet):
    queryset = HeroInfo.objects.all()
    serializer_class =  HeroInfoModelSerializer
    throttle_scope = 'seven'  # 指定此视图限流次数
  • 1
  • 2
  • 3
  • 4

过滤Filtering

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

pip install django-filter

在配置文件中增加过滤设置

INSTALLED_APPS = [
	...
    #过滤设置
    'django_filters',
]
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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


class HeroViewSet( ModelViewSet):
    queryset = HeroInfo.objects.all()
    serializer_class =  HeroInfoModelSerializer
    throttle_scope = 'seven'  # 指定此视图限流次数
    filter_fields = ['hname', 'hcomment']   # 指定可以过滤的字段

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

排序

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

  • 使用方法
    在类视图中设置子filter_backends, 使用 rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串中检查是否包含ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
    前端 可以 传递的ordering参数的可选字段值需要在 ordering_fields中指明
    例如:
from rest_framework.filters import OrderingFilter  # 排序过滤

class HeroViewSet(ModelViewSet):
    queryset = HeroInfo.objects.all()
    serializer_class =  HeroInfoModelSerializer
    throttle_scope = 'seven'  # 指定此视图限流次数
    # filter_fields = ['hname', 'hcomment']   # 指定可以过滤的字段
    filter_backends = [OrderingFilter]  # 排序过滤
    ordering_fields = ['id', 'hname']  # 可排序查询的字段
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

查询语法:

http://127.0.0.1:8000/book/heros/?ordering=-id

分页Pagination

REST framework提供了分页支持

  • 我们可以在配置文件中设置全局的分页方式, 如:
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE':100
}
  • 1
  • 2
  • 3
  • 4
  • 通过自定义的Pagination类,来为视图类加不同的分页行为,在视图中通过 pagination_class属性来指明

可选分页器

1)PageNumberPagination

引入 from rest_framework.pagination import PageNumberPagination
创建继承PageNumberPagination的类 (LargeResultsSetPagination)
在对于的视图类中 使用 pagination_class = LargeResultsSetPagination

参数
1. page_size = 6 # 每个页的数目
2. page_query_param = ‘page’ # 前端发送的页数关键字名,默认为"page"
3. page_size_query_param = ‘page_size’ # 前端发送的每页数目关键字名, 默认为None
4. max_page_size = 7 # 前端最多能设置的每页数量

前端访问网址形式:

http://127.0.0.1:8000/book/books/?page=2&page_size=8

视图代码

class LargeResultsSetPagination(PageNumberPagination):
    page_size = 6   # 每个页的数目
    page_query_param = 'page'  # 前端发送的页数关键字名,默认为"page"
    page_size_query_param = 'page_size'  # 前端发送的每页数目关键字名, 默认为None
    max_page_size = 7    # 前端最多能设置的每页数量


class BookViewSet( ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class =  BookInfoModelSerializer
    permission_classes = [IsAuthenticated]  # 只有通过认证的用户
    throttle_scope = 'seven'  # 指定此视图限流次数
    pagination_class =  LargeResultsSetPagination
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2)LimitOffsetPagination

在offset指定的数值向后偏移limit个数量

参数

  1. default_limit = 5 # 默认限制,默认值与PAGE_SIZE 设置一致
  2. limit_query_param = ‘limit’ # limit参数名 默认为"limit"
  3. offset_query_param = ‘offset’ # offset参数名,默认为’offset’
  4. max_limit = 7 # 最大limit限制,默认为None

代码展示:

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
class LimitOffset(LimitOffsetPagination):
    default_limit = 5  # 默认限制,默认值与PAGE_SIZE 设置一致
    limit_query_param = 'limit'   # limit参数名 默认为"limit"
    offset_query_param = 'offset'  # offset参数名,默认为'offset'
    max_limit = 7  # 最大limit限制,默认为None
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

前端访问格式:

http://127.0.0.1:8000/book/books/?limit=8&offset=3

异常处理

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

在项目根路径下创建 exceptions.py文件,进行添加异常捕获

from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework import status
from django.db import DatabaseError
from rest_framework.response import Response


'''在DRF的异常捕获基础增加数据库的异常捕获'''
def exception_handler(exc, context):

    # 先用户DRF自带的异常捕获去拦截 , 这里的drf_exception_handler就是rest_framework.views中的exception_handler,起的别名
    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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

修改配置文件

REST_FRAMEWORK = {
	...
    # 修改捕获异常函数
    #'EXCEPTION_HANDLER':'my_project.my_app.utils.custom_exception_handler'
    'EXCEPTION_HANDLER':'exceptions.exception_handler'
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

自动生成接口文档

自动接口文档能生成的是继承自APIView及其子类的视图

  1. 安装依赖(需要coreapi库的支持)

pip install coreapi

  1. 设置接口文档访问路径
    (在总路由中添加接口文档路径,
    文档路由对应的视图配置为 rest_framework.documentation.include_docs_urls,
    参数 title为接口文档网站标题)
 from django.contrib import admin
from django.urls import path,include
from rest_framework.documentation import include_docs_urls



urlpatterns = [
    ...
    path(r'docs/',include_docs_urls(title='API文档')),
	...
]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3.增加文档描述信息(在模型类中增加’’’ ‘’'对api的说明)

class BookViewSet( ModelViewSet):
    '''
    list:
    返回所有图书信息77

    create:
    增加图书
    '''
    queryset = BookInfo.objects.all()
    serializer_class =  BookInfoModelSerializer
    permission_classes = [IsAuthenticated]  # 只有通过认证的用户
    throttle_scope = 'seven'  # 指定此视图限流次数
    pagination_class =  LimitOffset

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 可能会报错(AttributeError: ‘AutoSchema’ object has no attribute ‘get_link’),在配置文件中添加如下
REST_FRAMEWORK = {
    ...
    # 重新指定schema_class的配置(接口文档)
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

谢谢观看~

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/71615
推荐阅读
相关标签
  

闽ICP备14008679号