06自定义过滤器,分页器,全局异常,封装Response,

1 自定制过滤器

1.1:基于drf的filter来写

1.1.1步骤

  1. 写一个类SearchBaseFilter,继承BaseFilterBackend

  2. 重写filter_queryset方法,在该方法内部进行过滤(自己设置的过滤条件)

  3. 返回queryset对象(过滤后的queryset对象)

  4. 配置在视图类中

filter_backends = [SearchBaseFilter,]
示例
from rest_framework.filters import BaseFilterBackend
class SearchBaseFilter(BaseFilterBackend):
    """
    A base class from which all filter backend classes should inherit.
    """
   
    def filter_queryset(self, request, queryset, view):
        search_name = request.data.get('search') or request.GET.get('search')
        if not search_name:
            return queryset
        return queryset.filter(name__contains=search_name) # name必须是模型字段,这个例子理解起来简单,但是写死了

完整版

urls.py

from django.urls import path
from work import views

urlpatterns = [
    path('student/', views.Student.as_view({'get': 'list', 'post': 'create'})),
]

views.py

from django.shortcuts import render

# Create your views here.


from . import models
from . import serializer
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
from rest_framework.filters import BaseFilterBackend


class SearchBaseFilter(BaseFilterBackend):
    """
    A base class from which all filter backend classes should inherit.
    """
    def filter_queryset(self, request, queryset, view):
        search_name = request.data.get('search') or request.GET.get('search')
        if not search_name:
            return queryset
        return queryset.filter(name__contains=search_name)


class Student(mixins.ListModelMixin,mixins.CreateModelMixin,GenericViewSet):
    serializer_class = serializer.StudentModelSerializer
    queryset = models.Student.objects.all()
    filter_backends = (SearchBaseFilter,)

models.py

from django.db import models

# Create your models here.
class Student(models.Model):
    choice_sex = ((1, '男'), (2, '女'), (3, '未知'))
    name = models.CharField(max_length=32)
    sex = models.SmallIntegerField(choices=choice_sex, default=1) #  get_sex_display
    age = models.IntegerField()

2 分页器(三种)重点如何使用

2.1:PageNumberPagination:普通分页

2.1.1:常用属性

page_size = api_settings.PAGE_SIZE  # 每页显示多少条
page_query_param = 'page'           # 查询参数
page_size_query_param = size        # 查询的时候指定每页显示多少条
max_page_size = 10                # 每页最多显示多少条

2.1.2: APIView下使用分页器

urls.py

from django.urls import path
from work import views

urlpatterns = [
    path('student/', views.APIStudent.as_view()),
]

views.py

class StudentPageNumberPagination(PageNumberPagination):
    page_size = 10
    page_query_param = 'page'
    page_size_query_param = 'size'
    max_page_size = 5


class APIStudent(APIView):
    def get(self,request,*args,**kwargs):
        student_list=models.Student.objects.all()
        page=StudentPageNumberPagination()
        res=page.paginate_queryset(student_list,request,self)
        ser=serializer.StudentModelSerializer(res,many=True)
        return page.get_paginated_response(ser.data)

image-20201204215208546

2.1.3:GenericAPIView+ListModelMixin下使用分页器

urls.py

from django.urls import path
from work import views

urlpatterns = [
    path('student/', views.Student.as_view({'get': 'list', 'post': 'create'})),

]

views.py


class StudentPageNumberPagination(PageNumberPagination):
    page_size = 10
    page_query_param = 'page'
    page_size_query_param = 'size'
    max_page_size = 5


class Student(mixins.ListModelMixin, mixins.CreateModelMixin, GenericViewSet):
    serializer_class = serializer.StudentModelSerializer
    queryset = models.Student.objects.all()
    # filter_backends = (SearchBaseFilter,)
    pagination_class = StudentPageNumberPagination

2.2:LimitOffsetPagination:偏移分页

2.2.1:常用属性

default_limit = api_settings.PAGE_SIZE  # 默认条数
limit_query_param = 'limit'             # 查询时,指定查询多少条
offset_query_param = 'offset'           # 查询时,指定的起始位置是哪 
max_limit = None                        # 查询时,最多返回多少条

2.2.2: APIView下使用分页器

class StudentLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 5
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    max_limit = 10


class APIStudent(APIView):
    def get(self,request,*args,**kwargs):
        # 查询所有数据
        student_list=models.Student.objects.all()
        # 实例一个对象
        page=StudentLimitOffsetPagination()
        # 获取分页的数据object
        res=page.paginate_queryset(student_list,request,self)
        # 序列化分页数据
        ser=serializer.StudentModelSerializer(res,many=True)
        # 直接返回序列数据
        return page.get_paginated_response(ser.data)

2.2.3:GenericAPIView+ListModelMixin下使用分页器

class StudentLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 5
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    max_limit = 10


class Student(mixins.ListModelMixin, mixins.CreateModelMixin, GenericViewSet):
    serializer_class = serializer.StudentModelSerializer
    queryset = models.Student.objects.all()
    pagination_class = StudentLimitOffsetPagination

image-20201204214519021

2.3:CursorPagination:游标分页

2.3.1:常用属性

cursor_query_param = 'cursor'  # 查询的时候,指定的查询方式
page_size = api_settings.PAGE_SIZE # 每页显示多少条
ordering = '-created'   # 排序方式
page_size_query_param = size  # 查询的时候指定每页显示多少条
max_page_size = None          #每页最多显示多少条

2.3.2: APIView下使用分页器

from . import models
from . import serializer
from rest_framework.viewsets import GenericViewSet

from rest_framework.views import APIView
from rest_framework.response import Response
from collections import OrderedDict


from rest_framework.pagination import  CursorPagination




class StudentCursorPagination(CursorPagination):
    cursor_query_param = 'cur'  # 查询的时候,指定的查询方式
    page_size = 5
    ordering = 'id'  # 排序方式
    page_size_query_param = 'size'  # 查询的时候指定每页显示多少条
    max_page_size = 10

from rest_framework.response import Response
class APIResponse(Response):
    def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, content_type=None, **kwargs):
        dic = {'code': code, 'msg': msg}
        if data:
            dic['data'] = data

        dic.update(kwargs) # 这里使用update
        super().__init__(data=dic, status=status,
                         template_name=None, headers=headers,
                         exception=False, content_type=content_type)

class APIStudent(APIView):
    def get(self,request,*args,**kwargs):
        student_list=models.Student.objects.all()
        page=StudentCursorPagination()
        res=page.paginate_queryset(student_list,request,self)
        ser=serializer.StudentModelSerializer(res,many=True)
        data =OrderedDict([
            ('next', page.get_next_link()),
            ('previous', page.get_previous_link()),
            ('results', ser.data)
        ])

        return APIResponse(data=data)

2.3.3:GenericAPIView+ListModelMixin下使用分页器

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination


class StudentCursorPagination(CursorPagination):
    cursor_query_param = 'cur'  # 查询的时候,指定的查询方式
    page_size = 5
    ordering = 'id'  # 排序方式
    page_size_query_param = 'size'  # 查询的时候指定每页显示多少条
    max_page_size = 10


class Student(mixins.ListModelMixin, mixins.CreateModelMixin, GenericViewSet):
    serializer_class = serializer.StudentModelSerializer
    queryset = models.Student.objects.all()
    pagination_class = StudentCursorPagination

image-20201205154340238

APIView的分页模式
	-新建一个类,继承普通分页,重写四个属性
    -视图类写法如下
	class StudentApiView(APIView):
        def get(self,request):
            student_list=Student.objects.all()
            page=MyPageNumberPagination()# 实例化得到对象
            # 只需要换不同的分页类即可
            res=page.paginate_queryset(student_list,request,self)# 开始分页
            ser=StudentSerializer(res,many=True)
            return page.get_paginated_response(ser.data) # 返回数据

3 全局异常

统一接口的返回方式,即便视图函数执行出错

utils.py

from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status

def comm_handler(exc,context):
    response = exception_handler(exc, context)
    if response is None:
        print(response)
    return Response({'code':999,'msg':'未知错误!','status':status.HTTP_500_INTERNAL_SERVER_ERROR})

setings

REST_FRAMEWORK = {
    		'EXCEPTION_HANDLER':'app01.utils.common_exception_handler'
		}

4 封装Response对象

自定义自己的返回格式

from rest_framework.response import Response
class APIResponse(Response):
    def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, content_type=None, **kwargs):
        dic = {'code': code, 'msg': msg}
        if data:
            dic['data'] = data

        dic.update(kwargs) # 这里使用update
        super().__init__(data=dic, status=status,
                         template_name=None, headers=headers,
                         exception=False, content_type=content_type)
        

使用

from . import models
from . import serializer
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
from rest_framework.views import APIView
from rest_framework.response import Response
from collections import OrderedDict
from rest_framework.pagination import CursorPagination


class StudentCursorPagination(CursorPagination):
    cursor_query_param = 'cur'  # 查询的时候,指定的查询方式
    page_size = 5 #默认显示条数
    ordering = 'id'  # 排序方式
    page_size_query_param = 'size'  # 查询的时候指定每页显示多少条
    max_page_size = 10 # 最大显示条数

class APIResponse(Response):
    def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, content_type=None, **kwargs):
        dic = {'code': code, 'msg': msg}
        if data:
            dic['data'] = data

        dic.update(kwargs) # 这里使用update
        super().__init__(data=dic, status=status,
                         template_name=None, headers=headers,
                         exception=False, content_type=content_type)

class APIStudent(APIView):
    def get(self,request,*args,**kwargs):
        student_list=models.Student.objects.all()
        page=StudentCursorPagination()
        res=page.paginate_queryset(student_list,request,self)
        ser=serializer.StudentModelSerializer(res,many=True)
        data =OrderedDict([
            ('next', page.get_next_link()),
            ('previous', page.get_previous_link()),
            ('results', ser.data)
        ])

        return APIResponse(data=data)

image-20201205210513947

5 自动生成接口文档

5.1:安装coreapi,swagger
5.2:具体配置

urls.py

from rest_framework.documentation import include_docs_urls
path('docs/', include_docs_urls(title='图书管理系统api'))

setings.py

REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
	}
5.3写类视图(需要加注释)
class BookListCreateView(ListCreateAPIView):
        """
        get:
        返回所有图书信息.
        asdfasfda

        post:
        新建图书.
        """
        queryset = Student.objects.all()
        serializer_class = StudentSerializer
5.4:查看接口文档
只需要在浏览器输入,就可以看到自动生成的接口文档()
	http://127.0.0.1:8000/docs/
posted @ 2020-12-29 17:30  为了等  阅读(98)  评论(0编辑  收藏  举报