如何自定义DjangoFilterBackend实现query包裹多字段搜索?
自定义DjangoFilterBackend适配
query[]格式的请求参数 嘿,这个需求其实很好实现,我们只需要给DjangoFilterBackend做个小扩展,重写它处理请求参数的逻辑就行。下面是具体步骤:
1. 编写自定义的FilterBackend类
首先在你的app里新建一个backends.py文件(或者随便哪个你习惯放工具类的地方),然后写这个自定义后端:
from django_filters.rest_framework import DjangoFilterBackend from django.http import QueryDict class CustomDjangoFilterBackend(DjangoFilterBackend): def get_filterset_kwargs(self, request, queryset, view): # 先继承父类的默认参数 kwargs = super().get_filterset_kwargs(request, queryset, view) # 专门提取`query[字段名]`格式的参数 filtered_params = {} for key, value in request.query_params.items(): # 检查参数键是否符合query[xxx]的格式 if key.startswith('query[') and key.endswith(']'): # 把`query[first_name]`转换成`first_name` field_name = key[6:-1] filtered_params[field_name] = value # 如果提取到了有效参数,就替换掉默认的data参数 if filtered_params: # 把普通字典转成Django的QueryDict,保持类型一致 new_data = QueryDict('', mutable=True) new_data.update(filtered_params) kwargs['data'] = new_data return kwargs
这段代码的核心逻辑就是:遍历请求里的所有参数,把query[xxx]格式的键提取成过滤器需要的普通字段名,然后把这些参数传给FilterSet。
2. 配置使用自定义后端
接下来你有两种方式启用这个自定义后端:
方式一:在单个视图/视图集里配置
直接在你的ViewSet里指定filter_backends为我们的自定义类:
from rest_framework import viewsets from .models import Contact from .serializers import ContactSerializer from .filters import ContactFilter # 你原来的FilterSet类 from .backends import CustomDjangoFilterBackend class ContactViewSet(viewsets.ModelViewSet): queryset = Contact.objects.all() serializer_class = ContactSerializer filter_backends = [CustomDjangoFilterBackend] # 替换成自定义后端 filterset_class = ContactFilter # 原来的过滤器配置不用改!
方式二:全局配置(所有视图生效)
如果你想让整个项目的过滤器都支持这种格式,直接在settings.py里修改REST_FRAMEWORK的配置:
REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': [ 'your_app_name.backends.CustomDjangoFilterBackend', # 其他你需要的后端,比如搜索、排序之类的 ] }
可选:同时兼容两种参数格式
如果你想同时支持原来的?first_name=Clair和新的?query[first_name]=Clair格式,只需要修改自定义后端里的循环逻辑,把普通参数也保留下来:
for key, value in request.query_params.items(): if key.startswith('query[') and key.endswith(']'): field_name = key[6:-1] filtered_params[field_name] = value else: # 保留普通格式的参数 filtered_params[key] = value
这样不管用户用哪种格式传参,过滤器都能正常工作啦。
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

