django-filter对ManyToMany字段实现多值过滤的方法
问题原因
你触发的'list' object has no attribute 'split'报错,核心原因是直接通过filter_fields自动生成多对多字段的__in过滤器时,django-filter默认绑定的表单组件会先把传入参数解析为列表,后续逻辑又尝试对列表对象调用split()方法做逗号分割,最终抛出类型错误。
默认配置下,__in查找的多值参数原生支持的是重复参数名传参格式,不识别逗号拼接的单参数值,你直接用users__in=1,2的格式传参就会触发组件逻辑冲突。
解决方案
不要直接使用filter_fields自动生成过滤器,显式自定义FilterSet类,针对多对多字段配置适配的组件即可。
首先定义自定义过滤器类
from django_filters import rest_framework as filters from .models import Ticket, User class TicketFilter(filters.FilterSet): # 支持逗号分隔传参的多用户匹配(OR逻辑:匹配分配给任意一个指定用户的工单) users = filters.ModelMultipleChoiceFilter( field_name="users", queryset=User.objects.all(), # 绑定CSV组件识别逗号分隔的多值 widget=filters.CSVWidget() ) # 兼容__in后缀的传参习惯 users__in = filters.ModelMultipleChoiceFilter( field_name="users", queryset=User.objects.all(), widget=filters.CSVWidget() ) # 同时适配status字段的多值过滤 status__in = filters.CharFilter( lookup_expr="in", widget=filters.CSVWidget() ) class Meta: model = Ticket fields = ["status", "status__in", "users", "users__in"]如果需要匹配同时分配给所有指定用户的工单(AND逻辑),给对应
ModelMultipleChoiceFilter加上conjoined=True参数即可。修改视图配置,替换原有
filter_fields为自定义过滤器类class TicketViewSet(ModelViewSet): queryset = Ticket.objects.all() filter_backends = (filters.DjangoFilterBackend,) # 删除原来的filter_fields配置,替换为下面的配置 filterset_class = TicketFilter
可用请求格式
配置完成后,两种传参格式都可以正常生效:
- 逗号分隔格式(和你之前尝试的写法一致)
http://localhost:8000/tickets?users__in=1,2 - 重复参数名格式(django-filter原生默认支持的格式)
http://localhost:8000/tickets?users=1&users=2
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

