drf之过滤排序分页异常处理

1 drf回顾

# 入门规范
    -前后端开发模式
    -API接口
    -接口测试工具-postman
    -restful规范(10条)
    -drf快速入门   (django的app,只能django框架使用)
        -drf最新版,最低支持django 2.x以上

 #  序列化组件
    -queryset对象:orm查询多个结果就是qs对象
    -把对象(qs)对象转成字典  many=True
    -把前端传入的json格式字符串,转成对象保存
    -Serializer 和 ModelSerializer
        - serializer = StudentSerializer(instance=student)
        - serializer.data---->就是序列化后的字典
    -字段(CharField,IntegerField)
    -字段属性(read_only,write_only)

    -反序列化
        -新增
        -serializer = StudentSerializer(data=request.data)
        -serializer.save()  # Serializer重写create,ModelSerializer不需要重写
        -修改
        -serializer = StudentSerializer(instance=对象,data=request.data)
        -serializer.save()  # Serializer重写updata,ModelSerializer不需要重写

     -数据校验(反序列化)
        -字段自己的校验规则
        -钩子函数

 # 请求和响应
    -Request对象:新的request
        -request.data  
        -request.query_params
        -request.xx  # 就是原来request对象的属性
        -处理什么格式的请求(urlencode,form-data,json)
            -全局配置
                REST_FRAMEWORK = {
                    'DEFAULT_PARSER_CLASSES': [
                        'rest_framework.parsers.JSONParser', # json
                        'rest_framework.parsers.FormParser', # urlencoded
                        'rest_framework.parsers.MultiPartParser',# form-data
                    ],
                }
            -局部配置
            class BookView(APIView):
                parser_classes = [JSONParser]


        ## 新手四件套
        obj=HttpResonose()
        obj=render--->函数,打开模板,去做替换(模板语法dtl),生成一个HttpResonose的对象
        obj=redirect--》生成一个HttpResonose的对象
        obj=JsonResponse--》生成一个HttpResonose的对象
        obj['xx']=xx # 向响应头写数据


       -Response对象
            -from rest_framework.response import Response
            -data=None,   响应的数据,字典,字符串
            -status=None,  响应状态码,1,2,3,4,5
            -headers={'xx':'xx'},  响应头 (响应对象['xx']=xx)

            -响应格式样子(json,浏览器访问的)
                -全局配置
                REST_FRAMEWORK = {
            'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
                'rest_framework.renderers.JSONRenderer',  # json渲染器
                'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
            )
        }
                -局部配置
                    class BookView(APIView):
                        render_classes = [JSONRenderer]

# 视图
    -2个视图基类 
        -APIView
        -GenericAPIView
            -queryset类属性
            -serializer_class类属性
            -ser=get_serializer(instance=对象,many=True) 方法
            -get_queryset(self) 方法
            -get_object(self)方法
      -5个视图扩展类(不是视图类),每个类就写了一个方法,需要配合上面两个使用
            -CreateModelMixin
            -ListModelMixin
            -RetrieveModelMixin
            -UpdateModelMixin
            -DestroyModelMixin
        -9个视图子类    
        -视图集
            -ModelViewSet
            -ReadOnlyModelViewSet
            -ViewSetMixin 类,没有集成任何类--》写了一个方法as_view---》路由写法变了---》自动生成路由
            -ViewSet:APIView与ViewSetMixin
            -GenericViewSet:GenericAPIView与ViewSetMixi

# 路由
    -继承ViewSetMixin及子类,路由写法变了
        -url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
         -自动生成路由
             -SimpleRouter(用的多)
             -DefaultRouter
             -from rest_framework import routers
                router = routers.SimpleRouter()
                router.register(r'router_stu', StudentModelViewSet, base_name='student')
             -urlpatterns += router.urls
            -url(r'^', include(router.urls))

   -action装饰器
      @action(methods=['get'], detail=False)
      def login(self, request): 



 # 三大认证()
     -认证(判断是否登录)
         -写一个认证类,继承BaseAuthentication,重写authenticate
         -在authenticate中认证,认证通过返回None或者两个值


          -局部使用和全局使用
     -权限(登录成功,是否能访问接口)
          -写一个类,继承BasePermission,重写has_permission方法,有权限,返回True,没有权限,返回False
           -局部和全局使用
     -频率(根据ip,根据用户限制每分钟只能访问多少次)
          -#写一个类,继承自SimpleRateThrottle,(根据ip限制)
    from rest_framework.throttling import SimpleRateThrottle
    class VisitThrottle(SimpleRateThrottle):
        scope = 'luffy'
        def get_cache_key(self, request, view):
            return request.META.get('REMOTE_ADDR') # 返回什么,就以什么限制
#在setting里配置:(一分钟访问三次)
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES':{
        'luffy':'3/m'  # key要跟类中的scop对应
    }
}

         -局部和全局使用

2 过滤排序分页异常处理

2.1 过滤

# 只针对于查询所有接口
# 127.0.0.1:8000/four/students/?sex=1

# 方式一:笨办法
    def list(self, request, *args, **kwargs):
        query=request.GET.get('name')
        qs=self.get_queryset().filter(name=query)
        ser=self.get_serializer(instance=qs,many=True)
        return Response(ser.data)
# 方式二:使用内置的过滤类(可以自己写,使用第三方)
    filter_backends=[SearchFilter,]   ## 过滤类:可以自己写,也可以用内置,使用第三方
    # SearchFilter类中通过反射获取的字段
    search_fields=['name','publish'] # 按那个字段过滤,可以模糊匹配
    # http://127.0.0.1:8000/book/?search=条件  并且支持模糊匹配

2.1 排序

# class BookView(ViewSetMixin, ListAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     ### 方法一:笨办法
#     # def list(self, request, *args, **kwargs):
#     #     query=request.query_params.get('ordering')
#     #     qs = self.get_queryset()
#     #     if query:
#     #         qs=qs.order_by(query)
#     #     ser=self.get_serializer(instance=qs,many=True)
#     #     return Response(ser.data)
#
#     ### 方式二:
#     filter_backends = [OrderingFilter]  # 内置的排序类
#     ordering_fields=['price']
#     # http://127.0.0.1:8000/book/?ordering=price
#     # http://127.0.0.1:8000/book/?ordering=-price




### 排查过滤连用
# class BookView(ViewSetMixin, ListAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     ### 方式:
#     filter_backends = [SearchFilter,OrderingFilter]  # 放在第一位的,最好能优先过滤掉很多数据
#     ordering_fields=['price']
#     search_fields = ['publish']
#     # http://127.0.0.1:8000/book/?ordering=price
#     # http://127.0.0.1:8000/book/?ordering=-price

2.3 自定义过滤类

# 第一步,写一个类,继承基类BaseFilterBackend,重写某个方法filter_queryset,返回的数据就是过滤后的qs对象
# 配置一下,在视图类中配置
filter_backends = [FilterByName]

### 过滤类
from rest_framework.filters import BaseFilterBackend
class FilterByName(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        #http://127.0.0.1:8000/book/?name=红楼梦
        query=request.query_params.get('name')
        if query:
            return queryset.filter(name__contains= query )
        else:
            return queryset

        return queryset

### 视图类
# from .filters import FilterByName
# class BookView(ViewSetMixin, ListAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#     filter_backends = [FilterByName]

2.4 django-filter的简单使用

## 使用第三方:django-filter,需要安装 pip3 install django-filter
# 是一个app,需要在项目中注册
# 导入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','publish']  # 不支持模糊匹配,只支持精准匹配,多个搜索条件是and关系

    如果需要修改and关系,可以使用Q

2.5 分页的使用

必须继承GengericAPIView及其子类

# 重写类方法
# 三种分页方式,需要重写类属性
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

class MyPageNumberPagination(PageNumberPagination):
    page_size = 2  # 每页显示的条数
    page_query_param = 'p'  #http://127.0.0.1:8000/book/?page=3
    page_size_query_param = 's'  # 每页显示多少条
    max_page_size = 3    # 每页最大显示3条


class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 1  # 每页显示的条数
    limit_query_param = 'limit'  # 取几条
    offset_query_param = 'offset' # 标杆,从第几个位置开始取   默认情况,每页显示一条
    max_limit = 5  # 最大每页显示多少条



# 分页速度快,有缺陷,只能上一页和下一页,不能直接跳到某一页,针对于数据量大,可以使用该分页方式
class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 不用动,没有用
    page_size = 3  # 每页显示多少条
    ordering = 'id' # 游标分页的原理,是先排序,然后使用游标标志位置,只能往前,往后,所以只能上一页和下一页



#### 在视图类中使用
class BookView(ViewSetMixin, ListAPIView):
    # 带分页功能
    pagination_class = CursorPagination # 配置成你重写的类

 # 全局使用
    'DEFAULT_PAGINATION_CLASS': None,

3 自动生成接口文档

# 土一点的公司:纯手写(word,md)
# 高级一点的:自动生成(drf:coreapi,swagger)
# 最高级的:接口文档平台
    -平台中录入:使用第三方
    -Yapi:百度开源的,把swagger自动生成的直接导入,修改



# 第一步:安装coreapi 
# 第二步:配置路由
from rest_framework.documentation import include_docs_urls
path('docs/', include_docs_urls(title='xx项目接口平台')),
# 第三步:配置文件中配置
REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',

}

# 第四步:写视图函数,在视图函数上加注释
posted @ 2022-02-15 21:25  一叶松  阅读(91)  评论(0)    收藏  举报