一、DRF 自定义 过滤、排序、分页 返回数据
通过 PageNumberPagination、LimitOffsetPagination、CursorPagination、返回的JSON数据中
- PageNumberPagination:不会携带总页数
- LimitOffsetPagination:不会携带总页数
- CursorPagination:不会返回总记录数据 以及 总页数
针对以上情况我们只能重写 list 方法,查询数据并且自己配置分页返回的数据,比如返回的状态码等,以下为 PageNumberPagination 分页类为例
以下演示会通过 过滤、排序、分页 进行统一的自定义返回的数据:
- 正常来讲我们的数据首先会进行过滤之后再对数据排序,再对过滤和排序后的数据进行分页显示
一、定义 Books ORM 类
编辑 models.py 定义 Books ORM类
from django.db import models
# 书籍表
class Books(models.Model):
name = models.CharField(verbose_name="书籍名称", max_length=32)
price = models.FloatField(verbose_name="价格")
二、定义序列化器 BookSerializer
创建 serializer.py 文件,定义序列化器 BookSerializer
from api import models
from rest_framework import serializers
# 定义 BookSerializer 继承 ModelSerializer
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Books # 指定使用的ORM类为 Books
fields = "__all__" # 指定显示所有字段
三、自定义分页类 CommonPageNumberPagination
创建 utils 文件,我自定义的分页类就写到 utils 文件当中了
# 导入 PageNumberPagination 分页类
from rest_framework.pagination import PageNumberPagination
# 自定义分页类 CommonPageNumberPagination,继承 PageNumberPagination
# 重新 PageNumberPagination 分页类中的类属性即可
class CommonPageNumberPagination(PageNumberPagination):
page_size = 2 # 默认每页显示2条数据
max_page_size = 10 # 最大每页显示10条数据
page_query_param = 'cansee_page' # 指定显示第几页时使用的key cansee_page
page_size_query_param = 'cansee_size' # 指定显示每页多少条数据时使用的key cansee_size
四、自定义过滤类 BookFilter
1、需安装依赖
pip install django-filter
2、注册 django-filter(修改 setting 文件)
INSTALLED_APPS = [
...
'django_filters', # 需要注册应用,
]
3、在视图 views.py 中自定义过滤器类
# 导入 DjangoFilterBackend 过滤类
from django_filters.rest_framework import DjangoFilterBackend
# 导入 django_filters 过滤类集合
import django_filters
# 导入 ORM models 模块
from api import models
# 自定义过滤类,注意过滤类中的 field_name 字段名称要与 ORM 类中的字段一致
class BookFilter(django_filters.FilterSet):
name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
price = django_filters.NumberFilter(field_name='price', lookup_expr='exact')
price__gt = django_filters.NumberFilter(field_name='price', lookup_expr='gt')
price__lt = django_filters.NumberFilter(field_name='price', lookup_expr='lt')
class Meta:
model = models.Books
fields = {
'name': ['icontains'],
'price': ['exact', 'gt', 'lt'],
}
使用这个过滤类时,您可以通过查询字符串参数来过滤数据,例如:
?name=example
: 用于按名称过滤,icontains 包含过滤?price=10.99
: 用于按价格精确过滤。exact 精确过滤?price__gt=10.99
用于按价格大于过滤。gt 大于过滤?price__lt=10.99
用于按价格小于过滤。lt 小于过滤
Meta 内部类:
model = Books
:指定此过滤器类作用于Books
模型。fields