使用DRF实现多对多关系场景下通过查询参数过滤API数据
Django DRF 按作者名筛选书籍功能实现方案
以下两种实现方式可按需选择:
方案一:直接重写 get_queryset 方法(无需额外依赖)
适合过滤逻辑简单、不想引入额外第三方包的场景,核心是通过 request.query_params.getlist() 读取多个同名参数,再通过多对多关联字段过滤:
from rest_framework import viewsets from .models import Book from .serializers import BookSerializer class BookViewSet(viewsets.ReadOnlyModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer def get_queryset(self): queryset = super().get_queryset() # 读取所有传入的author参数,返回列表 author_names = self.request.query_params.getlist('author') if author_names: # 若前端传参带单引号(如示例?author='xxx'),可加这行清理引号 cleaned_names = [name.strip("'") for name in author_names] # 多对多反向关联过滤:匹配任意一个作者名的书籍,distinct用于去重 queryset = queryset.filter(authors__name__in=cleaned_names).distinct() return queryset
方案二:使用 django-filter 库(更规范,适合复杂过滤场景)
如果项目后续有更多过滤需求,推荐用专门的过滤库实现,维护性更强:
步骤1:安装并配置依赖
首先安装包:pip install django-filter
然后在 settings.py 中注册应用:
INSTALLED_APPS = [ # ... 其他应用 'django_filters', ] # 全局配置DRF默认过滤后端(也可以单独在View里配置) REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': [ 'django_filters.rest_framework.DjangoFilterBackend', ], }
步骤2:自定义过滤器集
import django_filters from .models import Book class BookFilter(django_filters.FilterSet): # 指定author参数对应关联字段,AllValuesMultipleFilter自动支持多值传入 author = django_filters.AllValuesMultipleFilter(field_name='authors__name', lookup_expr='exact') class Meta: model = Book fields = ['author']
步骤3:View中绑定过滤器
class BookViewSet(viewsets.ReadOnlyModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer filterset_class = BookFilter # django-filter 2.x版本后用filterset_class代替旧版filter_class
注意事项
- 上述两种方案默认逻辑是:只要书籍关联的作者存在任意一个匹配传入的作者名,就返回该书籍。如果你的需求是书籍必须同时匹配所有传入的作者,则需要把过滤逻辑改为循环叠加过滤条件:
for name in cleaned_names: queryset = queryset.filter(authors__name=name) - 建议前端传参时省略单引号,直接使用
?author=something1&author=something2的格式,更符合HTTP参数规范,避免多余的字符串清理逻辑。
内容的提问来源于stack exchange,提问作者jokonoo
相关产品推荐
相关产品推荐

