如何用DRF、django-filter基于HyperlinkedIdentityField做多值查询过滤
问题修复方案
核心问题原因
- 之前自定义过滤器循环执行过滤的逻辑等价于生成
driver=1 AND driver=2的查询条件,不存在同时属于两个司机的合同,所以只会保留最后一次过滤的结果 - 默认的
FilterSet对关联字段生成的是ModelChoiceFilter,仅支持传入ID值,传入超链接字符串会触发参数校验失败,返回400错误
修复后代码
1. 自定义过滤器实现
from django_filters import BaseCSVFilter, CharFilter from django.urls import resolve from urllib.parse import urlparse, unquote def get_id_from_url(url): # 可根据需要添加异常捕获,处理无效URL的场景 return int(resolve(urlparse(unquote(url)).path).kwargs.get('pk')) class CustomHyperlinkedIdentityFilterList(BaseCSVFilter, CharFilter): def filter(self, qs, value): if not value: return qs # 批量转换所有超链接为资源ID target_ids = [get_id_from_url(item) for item in value] # 用IN查询一次性匹配所有关联对象 return qs.filter(**{f"{self.field_name}__id__in": target_ids})
2. 过滤器配置
class ContractFilter(FilterSet): driver = CustomHyperlinkedIdentityFilterList(field_name='driver') class Meta: model = Contract fields = ['driver']
效果验证
发起示例请求:/api/contract/?driver=http://localhost:8000/api/driver/1,http://localhost:8000/api/driver/2
即可返回两个司机对应的所有合同数据,符合业务需求。
内容的提问来源于stack exchange,提问作者Uldis
相关产品推荐
相关产品推荐

