Appearance
有些时候用户需要某个特定范围的文章(比如搜索功能),这时候后端需要把返回的数据进行过滤。
最简单的过滤方法就是修改视图集中的 queryset
属性了:
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.filter(author__username='Obama')
...
但是这样会导致原本正常的列表也都过滤了,太傻了。因此需要寻找更聪明的办法。
参数过滤
假设有如下带有参数的 GET 请求:
http://127.0.0.1:8000/api/article/?username=Obama
我们可以覆写 get_queryset()
方法来实现过滤:
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
...
def get_queryset(self):
queryset = self.queryset
username = self.request.query_params.get('username', None)
if username is not None:
queryset = queryset.filter(author__username=username)
return queryset
这样就实现了过滤。但是如此常用的功能,必然已经有现成的轮子了。在博客项目中使用轮子可以更快更好的完成任务,所以接下来就来看看通用的过滤功能。
注意上面那个请求尾部的斜杠。虽然在浏览器中这个斜杠是可选的,但是在命令行中发送请求是必须要携带的(DRF 3.11.0)。
通用过滤
还记得刚安装 DRF 时顺便安装的 django-filter
吗,这就是用于过滤的轮子,现在派上用场了。
要将它作为默认的过滤引擎后端,写到配置文件中:
python
# drf_vue_blog/settings.py
...
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
...
}
你也可以将其单独配置在特定的视图中:
python
from django_filters.rest_framework import DjangoFilterBackend
class ArticleViewSet(viewsets.ModelViewSet):
filter_backends = [DjangoFilterBackend]
filterset_fields = ['author__username', 'title']
...
如果要实现单纯的完全匹配,上面这样写就可以了,请求参数可以单个字段也可以联合:
python
C:\...>http http://127.0.0.1:8000/api/article/?author__username=dusai&title=newtest
在 windows 系统用 httpie 时,上述请求中的 & 符号需要加上双引号,即变成 "&"。这是因为 & 符是系统的预留符号。实际在接口中的请求是不需要引号的。
如果要实现更常用的模糊匹配,就可以使用 SearchFilter
做搜索后端:
python
# article/views.py
...
from rest_framework import filters
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsAdminUserOrReadOnly]
filter_backends = [filters.SearchFilter]
search_fields = ['title']
# 这个属性不需要了
# filterset_fields = ['author__username', 'title']
非常轻松就实现了对文章标题的检索。