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

##权限、认证源码(了解)###权限源码```python#继承了APIView才有的》执行流程》dispatch中的三大认证self.i


(资料图片仅供参考)

权限、认证源码(了解)权限源码
# 继承了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 OrderingFilterclass 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 SearchFilterclass 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 DjangoFilterBackendclass 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 MyFilterfrom rest_framework.filters import OrderingFilterclass 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 filtersfrom django.db.models import Qclass 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,MyCursorPaginationclass 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来
关键词:
责任编辑:hn1007