06自定义过滤器,分页器,全局异常,封装Response,
1 自定制过滤器
1.1:基于drf的filter来写
1.1.1步骤
-
写一个类SearchBaseFilter,继承BaseFilterBackend
-
重写filter_queryset方法,在该方法内部进行过滤(自己设置的过滤条件)
-
返回queryset对象(过滤后的queryset对象)
-
配置在视图类中
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)
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
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
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)
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/