drf认证组件/权限/频率 排序组件 分页组件

Drf认证组件

eg:个别接口需要登录后才可以使用 局部使用

# 需要编写一个认证类 
# 在py文件中创建一个认证类的py文件authentication.py

通过继承来编写:eg:登录验证

from rest_framework.authentication import BaseAuthentication
# 编写认证组件需要继承 认证类
from rest_framework.exceptions import AuthenticationFailed
# 认证失败报异常模块

class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.META.get('HTTP_TOKEN')
        # 从请求头中获取token
        if token:
            user_token = UserToken.objects.filter(token=token).first()
            # 判断前端传的token是否正确 是否存在
            if user_token:
                return user_token.usertoken, token
              # 存在即代表已登录,通过外键获得用户对象 返回
			  # 认证通过一定要返回2个数据,1,用户对象,2,用户token
            else:
                raise AuthenticationFailed('token认证失败')
                # 认证失败要抛异常 调用模块
        else:
            raise AuthenticationFailed('暂未登录')
            
 
# 视图类绑定认证---------------------------------------
class BooksDetailView(GenericViewSet, RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    authentication_classes = [LoginAuth]
    # 通过authentication_classes来设置执行的认证器,认证成功以后才可以使
    # 用类中的方法
    
    
总结:
# 1 写一个认证类,继承BaseAuthentication
# 2 重写authenticate方法,在该方法在中实现登录认证:token正确即为登录
# 3 如果认证成功,一定返回两个值【返回用户对象,和 token】
# 4 认证不通过,抛异常AuthenticationFailed
# 5 局部使用和全局使用
# 6 如果多个认证类同时使用,是从左到右顺序,如果都要依次认证,那第一个认证
# 类通过后需要返回none才会接着执行第二个认证类 最后一个认证类返回
# 数据对象 和 数据即可

全局使用/局部不使用

# 在settings.py文件中最下方添加该认证类,这样默认就是给所有的接口都生效

REST_FRAMEWORK = {
  'DEFAULT_AUTHENTICATION_CLASSES'['app01.authenticate.LoginAuth']
	}


# 如何要局部不使用:

class BooksDetailView(GenericViewSet, RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    authentication_classes = []
    # 只需要在局部把这个认证类置空即可,那么这个类里面的接口都不需要认证了

Drf权限组件

eg:某些接口需要管理员身份,或vip等才可以使用

局部配置

# 需要编写一个权限类 
# 在py文件中创建一个认证类的py文件permissions.py

from rest_framework.permissions import BasePermission
# 导入权限设置类


class CommonPermission(BasePermission):
  # 继承类并重新方法
    def has_permission(self, request, view):
        if request.user.user_type == 1:
          # 判断用户权限是否符合
            return True
          # 权限符合通过就返回 True
        else:
            self.message = f'您是{request.user.get_user_type_display()}'
            # 返回错误信息,错误信息在self.message中
            return False
          # 权限不对就返回 false
          
 知识点:{request.user.get_user_type_display()}
# 搭配数据库中choices=((1,'超级管理员'),(2,'普通用户'))使用
# 通过get_字段名__display()方法可以把数字对应的说明取出来



# 视图类----------------------------------------
class BooksDetailView(GenericViewSet, RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [CommonPermission]
    # 设置该接口需要的权限类即可
    # 局部配置

全局配置

# 在settings.py文件中最下方添加该认证类,这样默认就是给所有的接口都生效

REST_FRAMEWORK = {
  
  'DEFAULT_AUTHENTICATION_CLASSES':        ['app01.authentications.LoginAuth'],
    'DEFAULT_PERMISSION_CLASSES': ['app01.permissions.CommonPermission']
  
}
# 全局配置


# 局部禁止

class BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    authentication_classes = []
    permission_classes = []
    # 局部取消权限认证
   

总结:

# 1 写一个权限类,继承BasePermission
# 2 重写has_permission方法,在该方法在中实现权限认证,在这方法中,request.user就是当前登录用户
# 3 如果有权限,返回True
# 4 没有权限,返回False, 要定制返回的中文: self.message='中文'
# 5 局部使用和全局使用

Drf频率组件

# 需要编写一个频率类 
# 在py文件中创建一个认证类的py文件throttling.py

from rest_framework.throttling import SimpleRateThrottle
# 导入需要继承的类

class Throttling(SimpleRateThrottle):
    scope = 'booksListThrottling'
    # 设置这个类的别名
    def get_cache_key(self, request, view):
        return request.META.get('REMOTE_ADDR')
        # 这里返回什么就什么做限制,现在是已ip地址做限制
        # return request.user.pk 这种是按照用户id限制
        
        
视图类---------------------------------------
class BooksDetailView(GenericViewSet, RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    throttle_classes = [Throttling]
    # 导过来刚刚写的频率类即可生效
    
    
设置频率类的参数------------------------------
django的sttings文件中配置

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.authentications.LoginAuth'],
    'DEFAULT_PERMISSION_CLASSES': ['app01.permissions.CommonPermission'],
    'DEFAULT_THROTTLE_RATES': {
        'booksListThrottling': '5/m',
        # 配置别名为booksListThrottling的频率类,频率为1分钟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 = [] 

自定义频率类

class SuperThrottle(BaseThrottle):
    VISIT_RECORD = {}

    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        # 自己写逻辑,判断是否超频
        # (1)取出访问者ip
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走 {ip地址:[时间1,时间2,时间3,时间4]}
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        # (1)取出访问者ip
        ip = request.META.get('REMOTE_ADDR')
        import time
        ctime = time.time()
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
        if ip not in self.VISIT_RECORD:
            self.VISIT_RECORD[ip] = [ctime, ]
            return True
        # self.history  = [时间1]
        self.history = self.VISIT_RECORD.get(ip,[])
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        while self.history and ctime - self.history[-1] > 60:
            self.history.pop()
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        if len(self.history) < 3:
            self.history.insert(0, ctime)
            return True
        else:
           
            return False

    def wait(self):
        import time
        ctime = time.time()
        return 60 - (ctime - self.history[-1])



drf三种过滤方式

restful规范中要求,请求地址中带过滤条件
eg:
只有一个接口需要过滤和排序,就是:查所有接口

# 方式一: 内置模块 模糊搜索

from rest_framework.filters import SearchFilter
# 内置的过滤功能,模糊匹配
# 必须搭配GenericAPIView或其子类使用

lass BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    # 权限设置功能置空
    throttle_classes = [Throttling]
    # 频率设置功能
    filter_backends = [SearchFilter]
    # 固定语法用法 
    search_fields = ['name']
    # 配置要模糊搜索的表字段名
    
http://127.0.0.1:8003/api/books/?search=# 必要要用search来使用
# 这样就实现了模糊搜索 名字中带有海的图书名

精确查找 第三方查询模块Django-filter

from django_filters.rest_framework import DjangoFilterBackend
# 需要导入这个类  


# 视图类中代码
class BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    throttle_classes = [Throttling]
    filter_backends = [DjangoFilterBackend]
    # 固定配置用法 带入DjangoFilterBackend类
    filterset_fields = ['name']
    # 设置精确查找字段 也可以设置多个 and关系
    
http://127.0.0.1:8003/api/books/?name=海贼王
# 不需要搭配search来使用了
# 只能精确查找,找不到返回空

自定义搜索类

# 需要编写一个频率类 
# 在py文件中创建一个认证类的py文件filter.py 存放编写的自定义过滤类

from rest_framework.filters import BaseFilterBackend
# 继承该类 进行编写

class booksfilter(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # 在里面实现过滤,返回queryset对象就是过滤后的对象
        # eg:价格大于100的图书,
        price_gt = request.query_params.get('price_gt', None)
        # 从get请求头里面拿到要搜索的条件
        if price_gt:
            return queryset.filter(price__gt=int(price_gt))
            # 字段实现__gt大于方法 需要该字段为整形才可以
            # 将符合条件的对象返回出去
        else:
            return queryset
          
 视图类---------------------------

class BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    throttle_classes = [Throttling]
    filter_backends =   		[SearchFilter,DjangoFilterBackend,booksfilter]
    # 可以同时支持多个过滤类方法,从左到右生效
    search_fields = ['name','price']
    # 固定配置用法
    filterset_fields = ['name','price']
    # 对表字段name进行搜索,只支持精确搜索

# http://127.0.0.1:8003/api/books/?search=海   触发SearchFilter模糊搜索

# http://127.0.0.1:8003/api/books/?name=海贼王   DjangoFilterBackend的精确搜索
    
    
# http://127.0.0.1:8003/api/books/?price_gt=100
# 触发自己定制的搜索类,自己定制的方法price_gt 查找单价大于100的

排序的使用

使用drf内置模块即可

# 视图类----------

from rest_framework.filters import OrderingFilter


class BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    throttle_classes = [Throttling]
    filter_backends = [OrderingFilter,SearchFilter,DjangoFilterBackend,booksfilter]
    # 排序的类放到最前面
    search_fields = ['name','price']
    # 固定配置用法
    filterset_fields = ['name','price']
    ordering_fields = ['price']
    # 设置需要排序的字段



http://127.0.0.1:8003/api/books/?ordering=price
# 触发排序的方法 对price字段进行排序 默认升序 从小到大
# ordering=-price 从大到小 加上-号

分页

只有查询所有接口才有分页
def内置3个分页器

分页器一(最常用,网页端)

# 必须继承 GenericAPIView 或子类 才可以使用
# # 需要编写一个分页类 
# 在py文件中创建一个认证类的py文件Page.py

from rest_framework.pagination import PageNumberPagination

class booksPageNumber(PageNumberPagination):
    page_size = 2
    # 控制每页显示条数,每页显示2条
    page_query_param = 'page'
    # 查询第10页的数据,一般不需要改
    page_size_query_param = 'size'
    # page=10&size=5 查询第10页 每页显示2条
    max_page_size = 10
    # 每页最大显示条数设置
    

    
视图类-------------直接配置上就可以了

class BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    authentication_classes = []
    throttle_classes = []
    filter_backends = [OrderingFilter,SearchFilter,DjangoFilterBackend,booksfilter]
    search_fields = ['name','price']
    # 固定配置用法
    filterset_fields = ['name','price']
    ordering_fields = ['price']
    pagination_class = booksPageNumber
    # 这里配置上写好的booksPageNumber分页类就可以实现了
    
    
 http://127.0.0.1:8003/api/books/
 # 不写默认是第一页
 http://127.0.0.1:8003/api/books/?page=2%size=10
 # 查询第二页 显示10条,但是这个最大显示数还是根据分页类中设置的

分页器二(偏移取值)不常用

# 在py文件中创建一个认证类的py文件Page.py
from rest_framework.pagination import PageNumberPagination, \
    LimitOffsetPagination, CursorPagination

class booksLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 2
    # 控制每页显示条数,每页显示2条
    limit_query_param = 'limit'
    # 查询页数控制关键字  limit=2 查询第二页
    offset_query_param = 'offset'
    # offset=1 位置偏移设置,从第一个位置取 索引取值
    max_limit = 10
    # 最大显示数
    
    
 class BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    authentication_classes = []
    pagination_class = booksLimitOffsetPagination
    # 配置分页器
    
    
http://127.0.0.1:8003/api/books/?limit=4&offset=1
# 意思是 位置偏移1 从一个位置以后拿4个数据  12345拿2345

分页器三 游标分页 app项目经常使用

# 在py文件中创建一个认证类的py文件Page.py
from rest_framework.pagination import CursorPagination


class BooksCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'
    # "http://127.0.0.1:8003/api/books/?cursor=cD01",
    # 设置显示的关键词
    page_size = 2
    # 设置每页显示条数
    ordering = 'id'
    #游标分页自带排序,设置根据排序的字段
    
    
    
class BooksView(GenericViewSet, ListAPIView, CreateAPIView, ):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    authentication_classes = []
    throttle_classes = []
    filter_backends = [SearchFilter,DjangoFilterBackend,booksfilter]
    search_fields = ['name','price']
    # 固定配置用法
    filterset_fields = ['name','price']
    ordering_fields = ['price']
    pagination_class = BooksCursorPagination
    # 匹配游标分页类 使用游标分类后就不可以使用drf的排序了,因为游标分页自带排序
    
    
 # 游标分页只能下一页或者上一页,不能直接取中间的,类似app下滑上滑
 # 但游标分页效率最高 大数据量推荐使用
posted @   Python-moon  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示