泽恩小站-教程区 Help

过滤文章

有些时候用户需要某个特定范围的文章(比如搜索功能),这时候后端需要把返回的数据进行过滤。

最简单的过滤方法就是修改视图集中的 queryset 属性了:

class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.filter(author__username='Obama') ...

但是这样会导致原本正常的列表也都过滤了,太傻了。因此需要寻找更聪明的办法。

参数过滤

假设有如下带有参数的 GET 请求:

http://127.0.0.1:8000/api/article/?username=Obama

我们可以覆写 get_queryset() 方法来实现过滤:

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 时顺便安装的 django-filter 吗,这就是用于过滤的轮子,现在派上用场了。

要将它作为默认的过滤引擎后端,写到配置文件中:

# drf_vue_blog/settings.py ... REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'] ... }

你也可以将其单独配置在特定的视图中:

from django_filters.rest_framework import DjangoFilterBackend class ArticleViewSet(viewsets.ModelViewSet): filter_backends = [DjangoFilterBackend] filterset_fields = ['author__username', 'title'] ...

如果要实现单纯的完全匹配,上面这样写就可以了,请求参数可以单个字段也可以联合:

C:\...>http http://127.0.0.1:8000/api/article/?author__username=dusai&title=newtest

如果要实现更常用的模糊匹配,就可以使用 SearchFilter 做搜索后端:

# 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']

非常轻松就实现了对文章标题的检索。

Last modified: 06 January 2025