在Django Rest框架中过滤数据
Django REST框架的通用列表视图,默认会返回模型管理器的整个查询集。对于现实世界的应用,有必要对查询集进行过滤,以根据需要检索相关的结果。因此,让我们来讨论如何创建一个提供过滤功能的RESTful Web服务。
- DjangoFilterBackend
- SearchFilter
- OrderingFilter
注意:你可以参考文章中使用的项目的模型、序列化器和视图的可浏览的API部分。
DjangoFilterBackend
DjangoFilterBackend类用于根据指定的字段集来过滤查询结果。这个后端类为给定的字段自动创建一个FilterSet(django_filters.rest_framework.FilterSet)类。我们也可以通过自定义设置创建我们自己的FilterSet类。
为了在我们的Django Web服务中配置过滤器后端类,我们需要在虚拟环境中安装django-filter包。确保你退出Django开发服务器(Ctrl+C)并激活虚拟环境。让我们运行下面的命令。
pip install django-filter
安装后,我们需要在settings.py文件中把django_filters应用程序定义为INSTALLED_APPS。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Django REST framework
'rest_framework',
'robots.apps.RobotsConfig',
# Django Filters
'django_filters',
]
下一步,我们需要将django_filters中的DjangoFilterBackend类设置为默认的过滤器类。让我们在settings.py文件中的REST_FRAMEWORK字典中提到它。
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS'🙁
'django_filters.rest_framework.DjangoFilterBackend',
),
}
现在我们的RESTful网络服务被配置为利用django_filters.rest_framework.DjangoFilterBackend类所提供的过滤功能。让我们对检索机器人列表的机器人类进行过滤。RobotList类,如下所示。
class RobotList(generics.ListCreateAPIView):
queryset = Robot.objects.all()
serializer_class = RobotSerializer
name = 'robot-list'
filter_fields = (
'robot_category',
'manufacturer',
)
在这里,你可以注意到一个名为filter_fileds的属性,在这里我们指定要过滤的字段名。现在,我们可以根据机器人的类别(robot_category)和/或制造商来检索机器人。
让我们根据机器人的类别来过滤机器人。HTTPie的命令是: http “:8000/robot/?robot_category=2”
输出:
让我们尝试另一个HTTPie命令,根据机器人类别和制造商过滤机器人。这条HTTPie命令是
http “:8000/robot/?robot_category=2&manufacturer=1”
输出:
现在让我们检查一下可浏览API的功能。你可以浏览以下网址
http://127.0.0.1:8000/robot/
你可以点击右上角的过滤器按钮来利用过滤器功能。它将显示如下图所示
点击提交按钮,你将得到基于填充的过滤器字段的结果,如下所示。
SearchFilter
SearchFilter类支持基于单一查询参数的搜索功能,它是基于Django管理员的搜索功能。
默认情况下,SearchFilter类使用不区分大小写的部分匹配,并且它可以包含多个搜索词(应该是空白和/或逗号分隔的)。我们还可以通过在 search_fields 中预留各种字符来限制搜索行为。
- ‘^’以搜索为起点。
- ‘=’ 完全匹配。
- ‘@’ 全文搜索。( 用于Django的PostgreSQL后端)
- ‘$’ Regex搜索
默认情况下,搜索参数被命名为search,你可以用SEARCH_PARAM设置来覆盖它。让我们通过在REST_FRAMEWORK字典中添加rest_framework.filters.SearchFilter类来利用SearchFilter类。
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS'🙁
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
),
}
我们的RobotList类看起来如下。
class RobotList(generics.ListCreateAPIView):
queryset = Robot.objects.all()
serializer_class = RobotSerializer
name = 'robot-list'
search_fields = (
'^name',
)
search_fields属性指定了一个字符串的元组,它表示我们想在搜索功能中包括的字段名。
让我们搜索一下机器人,它以 “IRB “的名字开始。HTTPie的命令是
http “:8000/robot/?search=IRB”
输出:
OrderingFilter
OrderingFilter类允许你根据指定字段对结果进行排序。默认情况下,查询参数被命名为ordering,,它可以通过ORDERING_PARAM设置被覆盖。ordering_field属性指定了一个字符串的元组,它表示对结果进行排序的字段名。
如果你没有在视图上指定一个ordering_fields属性,过滤器类允许用户对序列化器_class属性指定的任何可读字段进行过滤。这允许用户对敏感信息进行排序,如密码哈希字段等,这可能导致意外的数据泄漏。你也可以通过在视图上设置一个排序属性来指定一个默认的顺序。它可以是一个字符串,也可以是一个字符串的列表/元组。
为了使用OrderingFilter类,我们需要将该类设置为REST_FRAMEWORK字典中的默认排序过滤器类。
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS'🙁
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.OrderingFilter',
),
}
让我们提一下RobotList类上的order_fields属性。代码如下。
class RobotList(generics.ListCreateAPIView):
queryset = Robot.objects.all()
serializer_class = RobotSerializer
name = 'robot-list'
ordering_fields = (
'price',
)
现在,让我们根据价格上涨的顺序来检索机器人。HTTPie的命令是
http “:8000/robot/?ordering=price”
输出: