drf入门之认证组件、权限组件、频率组件、过滤排序、分页

drf入门之认证组件、权限组件、频率组件、过滤排序、分页

认证组件

  • 认证组件使用步骤
# 有的接口需要登录后才能访问;有的接口,不登录就能访问,这是登录认证的限制   
# 写一个登录接口,返回token。以后只要带着token过来,就是登录了。不带,就没登录。
# 查询所有不需要登录就能访问
# 查询单个,需要登录才能访问

# 认证组件使用步骤
1、写一个认证类,继承BaseAuthentication
2、重写authenticate方法,在该方法在中实现登录认证:token在哪带的?
	如果认证它是登录了
3、如果认证成功,返回两个值[返回None或两个值]
4、认证不通过,抛异常AuthenticationFailed
5、局部使用和全局使用
	局部:只在某个视图类中使用[当前视图类管理的所有接口]
        class BookDetailView(ViewSetMixin, RetrieveAPIView):
            authentication_classes = [LoginAuth] 
    全局:全局所有接口都生效(登录接口不要)
    REST_FRAMEWORK = {
    	'DEFAULT_AUTHENTICATION_CLASSES':['app01.authenticate.LoginAuth']
	}
    
    局部禁用:
    	 class BookDetailView(ViewSetMixin, RetrieveAPIView):
            authentication_classes = [] 

  • 代码
# 视图
# 查询所有
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 查询单个
class BookDetailView(ViewSetMixin, RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # authentication_classes = [LoginAuth]  
    # 需要自己写一个认证类

# 认证类代码

class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 在这里实现认证,如果是登录的,继续往后走返回两个值,如果不是抛异常
        # 请求中是否携带token,判断是否登录,放在地址栏中
        token = request.query_params.get('token', None)
        if token:  # 前端传入token了,去表中查。如果能查到,登录了,返回两个值[固定的:当前登录用户,token]
            user_token = UserToken.objects.filter(token=token).first()
            if user_token:
                return user_token.user, token
            else:
                # 没有登录抛异常
                raise AuthenticationFailed('token认证失败')
        else:
            raise AuthenticationFailed('token没传')

# 路由代码
router.register('books', views.BookView, 'books')
router.register('books', views.BookDetailView, 'books')

"""
不要在配置文件中乱导入不使用的东西,否则会报错
"""

权限组件

  • 权限的使用
# 即便登录成功了,有些接口还是不能访问,因为没有权限
# 登录后,有的接口有权限访问,有的没有权限访问
# 查询单个和查询所有,都要登录才能访问----》全局认证
    查询单个需要超级管理员才能访问
    查询所有,所有登录用户都能访问   
# 权限是一个字段,在User表中,加入user_type字段

# 权限的使用
1、写一个权限类,继承BasePermission
2、重写has_permission方法,在该方法在中实现权限认证。在这方法中,request.user就是当前登录用户
3、如果有权限,返回True
4、没有权限,返回False,定制返回的中文: self.message='中文'
5、局部使用和全局使用
	-局部:只在某个视图类中使用【当前视图类管理的所有接口】
        class BookDetailView(ViewSetMixin, RetrieveAPIView):
    		permission_classes = [CommonPermission]
    -全局:全局所有接口都生效
          REST_FRAMEWORK = {
            'DEFAULT_PERMISSION_CLASSES': [
                'app01.permissions.CommonPermission',
            ],

        }
    
    -局部禁用:
    	 class BookDetailView(ViewSetMixin, RetrieveAPIView):
            permission_classes = [] 
            

频率组件

  • 使用步骤
# 控制某个接口访问频率(次数)
# 查询所有接口,同一个ip一分钟只能访问5次

# 使用步骤
1、写一个频率类,继承SimpleRateThrottle
2、重写get_cache_key方法,返回什么,就以什么做限制。如:ip,用户id做限制
3、配置一个类属性:scope = 'book_5_m'
4、在配置文件中配置
  'DEFAULT_THROTTLE_RATES': {
        'book_5_m': '5/m',
    },
5、局部使用和全局使用
	-局部:只在某个视图类中使用【当前视图类管理的所有接口】
        class BookDetailView(ViewSetMixin, RetrieveAPIView):
    		throttle_classes = [CommonThrottle]
    -全局:全局所有接口都生效
          REST_FRAMEWORK = {
             'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle'],

        }
    -局部禁用:
    	 class BookDetailView(ViewSetMixin, RetrieveAPIView):
            throttle_classes = [] 

过滤排序

  • 内置过滤类的使用
from rest_framework.filters import SearchFilter
# 用法是固定的 只有模糊匹配

class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 指定过滤类
    filter_backends = [SearchFilter]
    # 按照指定字段模糊匹配
    search_fields = ['name','price']  # 可以按名字模糊匹配或价格模糊匹配

    查询方式
    以url携带参数的形式 且参数名必须得是search
    如: http://127.0.0.1:8000/api/v1/books/?search=红
  • 使用第三方django-filter实现过滤
pip3.8 install django-filter

from django_filters.rest_framework import DjangoFilterBackend

class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 指定过滤类
    filter_backends = [DjangoFilterBackend]
    # 按照指定字段完整匹配
    filter_fields = ['name','price']  # 不是模糊匹配 而是完整匹配

    查询方式
    以url携带参数的形式 参数名为指定字段名
    如: http://127.0.0.1:8000/api/v1/books/?price=939&name=红楼梦 
	# 两个条件都得满足
    
  • 自己定制过滤类实现过滤
自定义过滤类:
    第一步:定义一个过滤类 继承BaseFilterBackend
    第二步:重写filter_queryset方法
    第三步:如果携带条件 那么返回对应结果
    第四步:没携带 那么返回所有数据

# 过滤类
class CommonFilter(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # 在里面实现过滤,返回qs对象,就是过滤后的数据
        price_gt = request.query_params.get('price_gt')
        if price_gt:
            qs = queryset.filter(price__gt=price_gt)
            return qs
        return queryset

# 视图类
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    filter_backends = [CommonFilter]  # 可以定制多个,从左往右,依次执行

  • 排序的使用
# 使用内置的就行
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [OrderingFilter]  
    ordering_fields = ['price']
    
 # 支持的查询方法:
    http://127.0.0.1:8000/api/v1/books/?ordering=price
    http://127.0.0.1:8000/api/v1/books/?ordering=-price
   http://127.0.0.1:8000/api/v1/books/?ordering=-id,price

分页

# 分页,只有查询所有接口,才有分页
# drf内置了三个分页器,对应三种分页方式
#内置的分页类不能直接使用,需要继承,定制一些参数后才能使用

# 分页使用,自定义一个分页类(三种)
class CommonPageNumberPagination(PageNumberPagination):
    page_size = 2  # 每页显示2条
    page_query_param = 'page'  # page=10  查询第10页的数据,每页显示2条
    page_size_query_param = 'size'  
    # page=10&size=5 查询第10页,每页显示5条
    max_page_size = 5  # 每页最大显示10条


# LimitOffset
class CommonLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3  # 每页显示2条
    limit_query_param = 'limit'  # limit=3   取3条
    offset_query_param = 'offset'  # offset=1  从第一个位置开始,取limit条
    max_limit = 5
    # offset=3&limit=2      0  1 2 3 4 5


# app 用下面
class CommonCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 查询参数
    page_size = 2  # 每页多少条
    ordering = 'id'  # 排序字段

# 配置在视图类上即可
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    authentication_classes = []
    throttle_classes = []
    # 之前的东西一样用 ,内置的分页类不能直接使用。需要继承,定制一些参数后才能使用
    # pagination_class = PageNumberPagination
    # 基本分页方式(基本是这种,网页端):http://127.0.0.1:8000/api/v1/books/?page=2&size=3
    # pagination_class = LimitOffsetPagination
    # 偏移分页 http://127.0.0.1:8000/api/v1/books/?limit=4&offset=1
    # 从第一条开始,取4条

    pagination_class = CommonCursorPagination
    # 游标分页,只能下一页,上一页,不能跳到中间,但它的效率最高,大数据量分页,使用这种较好
    
posted @ 2023-02-08 15:17  知了了了了  阅读(57)  评论(0)    收藏  举报