首页 > 编程语言 >drf——权限、认证源码分析、过滤、排序、分页

drf——权限、认证源码分析、过滤、排序、分页

时间:2023-05-25 22:44:59浏览次数:53  
标签:permission self request 认证 price 源码 排序 class drf

权限、认证源码(了解)

权限源码

# 继承了APIView才有的---》执行流程---》dispatch中的三大认证
		self.initial(request, *args, **kwargs)
	# 1. APIView的dispatch中self.initial(request, *args, **kwargs)
    	def initial(self, request, *args, **kwargs):
            self.perform_authentication(request)  # 认证
        	self.check_permissions(request)  # 权限
        	self.check_throttles(request)  # 频率
            
    # 2. 读权限:APIView的方法self.check_permissions(request)
    	def check_permissions(self, request):
            for permission in self.get_permissions():
            # self.get_permissions()是我们配置在视图类中permission_classer列表中的认证类实例化出来的一个一个对象
           """
           permission_classes = [AdminPermission,]
           self.get_permissions()是AdminPermission()实例化出的对象
           """
                if not permission.has_permission(request, self): # 权限没通过会执行
                # 写的权限类需要重写has_permission方法
                # permission是自己写的权限类的对象 
                # 对象点方法时 先从自己类中找has_permission
                # 后面括号中的self参数是视图类的对象
                    self.permission_denied(
                        request,
                        message=getattr(permission, 'message', None),
                        # self.message 错误文字
                        code=getattr(permission, 'code', None)
                    )
    
    # 3. APIView中的self.get_permissions()
    	def get_permissions(self):
        	return [permission() for permission in self.permission_classes]
        """
        permission_classes是我们配置在视图类中的权限类
        self是自己写的视图类的对象
        self.permission_classes获取所有配置的权限类
        列表生成式 也可以写成
        l = []
        for permission in self.permission_classes
        	l.append(permission())
       	return l
        """
        # 返回一个列表 列表中是一个个自己写的权限类的对象
        
# 总结
	写的权限类 一定要写一个方法has_permission,返回True或False 不写则报错
    配置在视图类上

认证源码

# 继承了APIView才有的---》执行流程---》dispatch中的三大认证
		self.initial(request, *args, **kwargs)
	# 1. APIView的dispatch中self.initial(request, *args, **kwargs)
    	def initial(self, request, *args, **kwargs):
            self.perform_authentication(request)  # 认证
        	self.check_permissions(request)  # 权限
        	self.check_throttles(request)  # 频率
            
    # 2. self.perform_authentication(request)
    	def perform_authentication(self, request):
        	request.user  # user这是个方法 包装成了数据属性
        """
        此时的request是走三大认证之前 dispatch中重新定义了新的request
        	request = self.initialize_request(request, *args, **kwargs)
        """
        
   # 3. Request类中的user
		@property
        def user(self):
            if not hasattr(self, '_user'):
                with wrap_attributeerrors():
                    self._authenticate()
            return self._user
        
   # 4. Request类的self._authenticate()
		def _authenticate(self):
            for authenticator in self.authenticators:
            """
            self.authenticators就是你写的认证类列表
            authenticators是在定义新的request时self.initialize_request调用这个方法的时候 return出的authenticators=self.get_authenticators(),
            get_authenticators是APIView中的方法
            def get_authenticators(self):
        		return [auth() for auth in self.authentication_classes]
        	循环视图类中的类属性authentication_classes获取列表中的每个认证类
        	然后给认证类加括号 实例化得到对象 再返回
        	即 authenticators是认证类实例化得到的对象放在列表中
        	
        	authenticator是一个个认证类实例化的对象
            """
                try:
                    user_auth_tuple = authenticator.authenticate(self)
                # authenticate是在认证类中重写的方法 如果认证成功返回的是元祖(user,token)
                except exceptions.APIException:
                    # 抛了异常被捕获了
                if user_auth_tuple is not None:  # 如果返回有值即认证通过执行
                    # self是Request的对象 
                    self.user, self.auth = user_auth_tuple  # (user,token)
                    return
            self._not_authenticated()
            
  # 总结
	1.认证类 必须写一个方法authenticate
    2.如果认证通过 可以返回None,也可以返回两个值 但是第一个值尽量是当前登录用户 第二个值一般放token
    3.认证失败 抛异常AuthenticationFailed('你没有登录,不能访问'),它继承了APIException,他能捕获

补充 Django中的国际化

# 只要做了国际化 会自动翻译成,当前国家的语言
from django.utils.translation import gettext_lazy as _
_('hello')

排序

# restful规范中
	-请求地址中带过滤条件
# 排序功能的接口:查询所有

from rest_framework.filters import OrderingFilter

class BookView(GenericViewSet,ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [OrderingFilter]  # 排序类
    ordering_fields = ['price','id']  # 指定哪些字段可以排序
    # ordering = ['id']  # 默认排序
    # http://127.0.0.1:8000/api/v1/books/?ordering=-price,-id
    # -是倒序 先按价格倒序排 再按id倒序排

过滤

# restful规范中
	-请求地址中带过滤条件
    
# 带过滤的接口只有:查询所有

'''1.内置过滤类'''
from  rest_framework.filters import SearchFilter

class BookView(GenericViewSet,ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [SearchFilter]
    # search_fields = ['name']
    # http://127.0.0.1:8000/api/v1/books/?search=红
    # 只要name中有红的都能搜索出
    search_fields = ['name','price']
    # http://127.0.0.1:8000/api/v1/books/?search=11
    # 只要name或者price中带有11的都能搜出来
    
'''2.第三方过滤类'''
# pip38 install django-filter
# 下载之后如果要使用的话 必须去配置文件INSTALLED_APPS下注册才可
from django_filters.rest_framework import DjangoFilterBackend
class BookView(GenericViewSet,ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['name','price']
    # http://127.0.0.1:8000/api/v1/books/?name=红楼梦&price=45
    # 按名字和价格精准匹配
    
'''3.自定义过滤类 很复杂的搜索 自己来写'''
'''视图类'''
from .filter import MyFilter
from rest_framework.filters import OrderingFilter

class BookView(GenericViewSet,ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # filter_backends = [MyFilter]
    # http://127.0.0.1:8000/api/v1/books/?name=红楼梦&price=11
    # 过滤出name为红楼梦或者price为11的
    # 过滤类可以配多个 执行顺序是从左往右
    filter_backends = [MyFilter,OrderingFilter]
    ordering_fields = ['price']
    # http://127.0.0.1:8000/api/v1/books/?price=44&name=红楼梦&ordering=-price
    # 过滤出name为红楼梦或者price为44的并且按价格降序排序
    
'''自定义过滤类'''
from rest_framework import filters
from django.db.models import Q

class MyFilter(filters.BaseFilterBackend):
    # 重写父类中的方法 返回的数据就是过滤后的数据
    def filter_queryset(self, request, queryset, view):
        price = request.query_params.get('price')
        name = request.query_params.get('name')
        queryset = queryset.filter(Q(price=price) | Q(name=name))
        return queryset

分页

# 查询所有接口,过滤和排序了,但是实际上,这个接口,都需要有分页功能
	-分页的展现形式
    	web:下一页点击
        app,小程序:下滑下一页
    -接口都一样,要支持分页
    
# 带过滤的接口只有:查询所有

# drf提供给咱们,三种分页方式
# 基本分页
# 偏移分页
# 游标分页
    
'''视图类'''
'''分页 --->>> 必须是获取所有的接口 必须继承GenericAPIView及其子类'''
from .page import MyPageNumberPagination,MyLimitOffsetPagination,MyCursorPagination

class BookView(GenericViewSet,ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    # pagination_class = MyPageNumberPagination  # 只能按一种方式分页,不要放到列表中了
    # # http://127.0.0.1:8000/api/v1/books/?page=1&page_size=3
    # # 查询第1页 每页显示3条

    # pagination_class = MyLimitOffsetPagination
    # # http://127.0.0.1:8000/api/v1/books/?limit=4&offset=3
    # # 从第三条数据开始,取4条

    pagination_class = MyCursorPagination
    # 只有上一页和下一页
    
'''分页类 page.py'''
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

# 基本分页
class MyPageNumberPagination(PageNumberPagination):
    # 重写的几个类属性 4个
    page_size = 2  # 每页显示的条数
    page_query_param = 'page'  # page=4 表示第4页
    page_size_query_param = 'page_size'  # page=4&page_size=5 表示查询第4页每页显示5条
    max_page_size = 5  # 每页最大显示多少条

# 偏移分页
class MyLimitOffsetPagination(LimitOffsetPagination):
    # 重写几个类属性 :4个
    default_limit = 2  # 每页显示多少条
    limit_query_param = 'limit'  # limit=3 这一页取3条
    offset_query_param = 'offset'  # 偏移量是多少 offset=3&limit=2 从第三条开始拿两条
    max_limit = 5  # 最多取5条

# 游标分页,只能上一页和下一页,不能直接跳到某一页,但是这个的速度快---》app上用它多
class MyCursorPagination(CursorPagination):
    # 重写几个类属性 :3个
    cursor_query_param = 'cursor'  # 查询参数,其实用不到
    page_size = 2  # 每页显示多少条
    ordering = 'id'  # 必须是要分页的数据表中的字段 一般按id来

标签:permission,self,request,认证,price,源码,排序,class,drf
From: https://www.cnblogs.com/XxMa/p/17433187.html

相关文章

  • drf过滤,drf排序,drf分页
    drf过滤:带过滤的接口只有:查询所有内置过滤类:http://127.0.0.1:8000/api/v1/books/?search=红http://127.0.0.1:8000/api/v1/books/?search=11此类查询类似于模糊查询fromrest_framework.filtersimportSearchFilterclassBookView(Gene......
  • drf-5个接口
    目录写接口前的准备1表模型序列化类一继承APIView+序列化类+Resonse写5个接口视图类路由二继承GenericAPIView+序列化类+Resonse写5个接口视图类路由三继承GenericAPIView+5个视图扩展类+序列化类+Response写接口视图类路由四基于视图子类写5个接口:9个视图子类--->视图......
  • 冒泡排序
    冒泡排序#include<stdio.h>intmain(){ints[10]={12,65,32,69,5,8,21,36,4,15};inti=0,j=0,c=0,b=0;intlen=sizeof(s)/sizeof(int);for(i=0;i<len;i++){printf("%d",s[i]);}printf("\n");for(j=0;j<len-1......
  • 选择排序算法之泛型优化
    选择排序算法工作原理:每一次从待排序的数据元素中选中最小的一个元素,然后,再从剩余未排序元素中继续寻找最小元素,将2个元素交换位置,就达到了已排序的元素一直是从小到大了。这个算法的时间复杂度为O(n²),空间复杂度为O(1)。/***@Author:翰林猿*@Description:选择排序*......
  • 直播商城系统源码,BottomSheetDialog实现-底部滑动栏
    直播商城系统源码,BottomSheetDialog实现-底部滑动栏bottom_popwindoow.xml中的代码 <?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"  android:orientation="vertical"......
  • 直播系统app源码,图片放大且有渐变色罩层出现
    直播系统app源码,图片放大且有渐变色罩层出现 <!DOCTYPEhtml><html><head><metacharset="utf-8"><title>5</title><style>.mask1,.text{position:relative;overflow:hidden;width:800px;height:500px;transition:all.5s;}    ......
  • AQS源码解读----AbstractQueuedSynchronizer
    36packagecn.com.pep;37importjava.util.concurrent.TimeUnit;38importjava.util.concurrent.locks.AbstractOwnableSynchronizer;39importjava.util.concurrent.locks.Condition;40importjava.util.concurrent.locks.LockSupport;41importjava.......
  • 归并排序Java版(图文并茂思路分析)
    归并排序工作原理:工作原理是将一个大问题分解成小问题,再将小问题分解成更小的。(乍一看就觉得是像一个递归)就像下图这样。然后不断的将其一份为二,分解成更小的排序。我们设一个函数叫MergeSort(arr,l,r)意思就是将arr数组下标为[l,r]之间的数进行排序。那么就开始不断的调用自......
  • tracee源码初探(二)TCP处理流程
    handleEvents(ctx),processNetCaptureEvents(若开启Capture.Net)协程一直常驻,并等待netCapChannel消息通知.当有事件传过来时,程序先看该事件是否需要处理,也就是说tracee是上报所有事件的,然后过滤来处理事件。在tracee.go中的initBPF函数里t.bpfModule.InitPerfBuf( "net_cap_......
  • 互联网医院系统源码:如何开发一款高效的互联网医院APP?
    一款高效的互联网医院APP可以为患者提供更便捷、快速、安全的医疗服务,同时也能为医生和医院提供更高效、精准的医疗管理和服务。本篇文章小编将从互联网医院系统源码的角度,给大家讲解如何开发一款优质的互联网医院APP。 一、互联网医院系统源码的基本架构互联网医院系统源码的基本......