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_filtersINSTALLED_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_paramlimit参数名,默认‘limit’
offset_query_paramoffset 参数名,默认为 ‘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 # 限制偏移分页

在这里插入图片描述

其他笔记

序列化器

视图路由

异常、登录认证

权限、限流

过滤、排序、分页