rest_framework_django 学习笔记五(过滤、排序、分页)
rest_framework_django 学习笔记五(过滤、排序、分页)
一、过滤
1、安装扩展 django-fitlter
对于列表数据可能需要根据字段进行过滤,我们可以通过添加 django-fitlter 扩展来增强支持。
pip install django-filter
2、设置
在配置文件中增加过滤后端的设置
#settings.py
INSTALLED_APPS = [
...
'django_filters',
...
]
REST_FRAMEWORK = {
# 过滤
"DEFAULT_FILTER_BACKENDS": (
'django_filters.rest_framework.DjangoFilterBackend',# 配置过滤
# "demo_app.filters.CustomDjangoFilterBackend", # 自定义 过滤
"rest_framework.filters.SearchFilter",
"rest_framework.filters.OrderingFilter",
),
}
3、视图中配置
在视图中添加 filter_fields 属性,指定可以过滤的字段
3.1 filterset_fields 精确查询
filterset_fields 是用于在视图集中指定哪些字段可以被用作过滤器的。这意味着你可以在视图集中定义这些字段,并使用它们来过滤查询结果。
from rest_framework.viewsets import ModelViewSet
class PublishModelviewSet(ModelViewSet):
"""
list:
返回数据列表
create:
创建出版社
retrieve:
单挑查询
update:
修改
destroy:
删除
"""
queryset = Publish.objects.all()
serializer_class = PublishSerializer
filterset_fields = ['name', 'city','id','email'] # 可过滤的字段 (搜索字段)

3.2 search_fields模糊查询
search_fields:用于指定哪些字段可以进行模糊匹配的过滤。也就是说,只要请求参数中的字段值出现在数据库中的实际值中,就会返回相应的结果。
from rest_framework.viewsets import ModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
class PublishModelviewSet(ModelViewSet):
"""
list:
返回数据列表
create:
创建出版社
retrieve:
单挑查询
update:
修改
destroy:
删除
"""
queryset = Publish.objects.all()
serializer_class = PublishSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter] # 后端过滤器
search_fields = ['city', 'email', ] # 模糊查询字段 ?search = value

4、自定义过滤类
4.1 首先需要安装django-filter库
pip install django-filter
4.2 settings.py 配置
在settings.py文件中添加django_filters到INSTALLED_APPS列表中:
INSTALLED_APPS = [
# ...
'django_filters',
]
在settings.py文件中配置REST_FRAMEWORK,添加自定义过滤器的路径:
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],# 过滤器
}
4.3 自定义过滤器类
import django_filters
from .models import Publish
class PublishFilter(django_filters.FilterSet):
name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
city = django_filters.CharFilter(field_name='city', lookup_expr='icontains')
class Meta:
model = Publish
fields = ['name', 'city']
| 参数 | 说明 |
|---|---|
| model | 指定模型类的名称,该过滤器应用于该模型类的实例。默认情况下,它与序列化器中的模型相同。 |
| field_name | 指定要在模型类上执行过滤的字段名称。该字段必须存在于指定的模型类中。 |
| exclude | 指定要从结果中排除的字段值。这可以用于排除不需要的值。 |
| lookup_expr | 指定要使用的查询表达式来执行过滤。它可以是以下之一:lookup_expr参数名表中 |
| condition | 指定一个可选的条件表达式,以进一步限制过滤结果。它应该是一个可调用的对象,接受单个参数作为条件表达式的结果,并返回一个布尔值以指示是否满足条件。例如,可以使用lambda函数来指定条件表达式:condition=lambda obj: obj.some_field > some_value。 |
| title | 指定过滤器在序列化器输出中使用的标题。如果未指定,则默认使用字段名作为标题。 |
| error_messages | 指定自定义的错误消息字典,用于在验证期间显示错误消息。如果未指定,则使用默认的错误消息字典。 |
| allow_multiple_values | 如果为True,则允许多个值与过滤条件匹配。默认值为False。 |
| required | 如果为True,则要求查询参数在请求中存在才能应用过滤。默认值为False。 |
| lookup_expr参数名 | 作用 |
|---|---|
| exact | 精确匹配(exact):当lookup_expr设置为exact时,只有当请求中的查询参数与序列化器字段的值完全匹配时,才会将该对象包含在过滤后的结果中。例如,如果序列化器字段的值为"hello",而请求中的查询参数为"hello",则该对象会被包含在过滤后的结果中。 |
| iexact | 不区分大小写匹配(iexact):当lookup_expr设置为iexact时,只有在请求中的查询参数与序列化器字段的值完全相同(不区分大小写)时,才会将该对象包含在过滤后的结果中。例如,如果序列化器字段的值为"Hello",而请求中的查询参数为"hello",则该对象不会被包含在过滤后的结果中。 |
| contains | 包含匹配(contains):当lookup_expr设置为contains时,只有当请求中的查询参数包含序列化器字段的值时,才会将该对象包含在过滤后的结果中。例如,如果序列化器字段的值为"hello",而请求中的查询参数为"helo"或"hello world",则该对象会被包含在过滤后的结果中。 |
| icontains | 不区分大小写包含匹配(icontains):当lookup_expr设置为icontains时,只有当请求中的查询参数包含序列化器字段的值(不区分大小写)时,才会将该对象包含在过滤后的结果中。例如,如果序列化器字段的值为"Hello",而请求中的查询参数为"helo"或"hello world",则该对象会被包含在过滤后的结果中。 |
| in | 范围匹配。只有当字段值在查询参数指定的范围内时,才会返回结果。 |
| gt | 大于匹配。只有当字段值大于查询参数时,才会返回结果。 |
| gte | 大于或等于匹配。只有当字段值大于或等于查询参数时,才会返回结果。 |
| lt | 小于匹配。只有当字段值小于查询参数时,才会返回结果。 |
| lte | 小于或等于匹配。只有当字段值小于或等于查询参数时,才会返回结果。 |
4.4 在视图中使用自定义过滤器
import django_filters
from .serializers import *
from .models import Publish
class PublishFilter(django_filters.FilterSet):
name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
city = django_filters.CharFilter(field_name='city', lookup_expr='icontains')
class Meta:
model = Publish
fields = ['name', 'city']
from rest_framework.viewsets import ModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
class PublishModelviewSet(ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = PublishFilter # 配置自定义过滤器

5、重写查询 filter_queryset
class PublishModelviewSet(ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
def filter_queryset(self, queryset):
# 在这里编写你的过滤逻辑
# 获取请求中携带的参数 self.request.query_params.get('field_name', None)
name = self.request.query_params.get('name', None)
if name is not None:
queryset = queryset.filter(name__icontains=name)
return queryset

二、排序
默认是按ID升序排序
对于列表数据,REST framework 提供了OrderIMGFilter 过滤来帮助我们快速指明数据按照指定字段进行排序。
使用方法:
在类视图中设置 filter_baxkends,使用rest_framework,fillers,orderingfilter 过滤,REST gramework 会在请求的查询字符串参数中检查是否包含 ordering 参数,如果包含了 ordering 参数,则按照 ordering 参数指明的排序字段对数据集进行排序。
前端可以传递的 orderding 参数的可选字段值需要在 ordering _fields 中指明:
from rest_framework.viewsets import ModelViewSet
from rest_framework.filters import OrderingFilter
class PublishModelviewSet(ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
filter_fields = '__all__'
# 指定过滤后端为排序
filter_backends = [OrderingFilter]
ordering_fields = ['id','city'] # 排序 ?ordering=-id
# ordering_fields = "__all__" # 排序 ?ordering=-id

三、分页
1、全局配置
REST framework 提供了分页的支持。
我们可以在配置文件中设置全局分页方式,如:
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", # 分页
"PAGE_SIZE":1,# 每页显示多少条
}

2、自定义分页
2.1 视图中限制
也可以通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过 pagination_class 属性来指明
from rest_framework.pagination import PageNumberPagination
class Page(PageNumberPagination):
page_size = 2 # 分页的数量
page_size_query_param = 'limit' # 页面大小查询参数
max_page_size = 3 # 最大每页数量
page_query_param='page' # 前端请求字符串的关键字,指定显示第几页的名字
from rest_framework.viewsets import ModelViewSet
from rest_framework.pagination import PageNumberPagination
class PublishModelviewSet(ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
pagination_class = Page

2.2 全局配置 自定义分页
#utils.py
from rest_framework.pagination import PageNumberPagination
class CustomPagination(PageNumberPagination):
page_size = 2 # 分页的数量
page_size_query_param = 'limit' # 页面大小查询参数
max_page_size = 3 # 最大每页数量
page_query_param='page' # 当前页码
在 settings.py 配置全局自定义分页
# settings.py
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "demo_app.utils.CustomPagination", # 自定义分页
}

注意:如果在视图内关闭分页功能,只需要在视图内设置
pagination_class=None
3、可选分页器
3.1 PageNumberPagination (推荐)
前端页面访问网址形式:
?page=4&page_size=4
| 参数 | 说明 |
|---|---|
| page_size_query_param | 前端发送的每页数目关键字名,默认为None |
| page_size | 每页数目 |
| page_query_param | 前端页面发送页数关键字,默认为page |
| max_page_size | 限制最多显示数目 |
3.2 LimitOffsetPagination (限制偏移分页)
前端页面访问网址
?limit=100&offset=400
可以在子类中定义的属性:
| 参数 | 说明 |
|---|---|
| default_limit | 默认限制,默认值与PAGE_SIZE |
| limit_query_param | limit参数名,默认‘limit’ |
| offset_query_param | offset 参数名,默认为 ‘offset’ |
| max_limit | 最大limit限制,默认 None |
from rest_framework.viewsets import ModelViewSet
from rest_framework.pagination import LimitOffsetPagination
class PublishModelviewSet(ModelViewSet):
queryset = Publish.objects.all()
serializer_class = PublishSerializer
pagination_class = LimitOffsetPagination # 限制偏移分页
