You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

django-filter对ManyToMany字段实现多值过滤的方法

问题原因

你触发的'list' object has no attribute 'split'报错,核心原因是直接通过filter_fields自动生成多对多字段的__in过滤器时,django-filter默认绑定的表单组件会先把传入参数解析为列表,后续逻辑又尝试对列表对象调用split()方法做逗号分割,最终抛出类型错误。

默认配置下,__in查找的多值参数原生支持的是重复参数名传参格式,不识别逗号拼接的单参数值,你直接用users__in=1,2的格式传参就会触发组件逻辑冲突。

解决方案

不要直接使用filter_fields自动生成过滤器,显式自定义FilterSet类,针对多对多字段配置适配的组件即可。

  1. 首先定义自定义过滤器类

    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参数即可。

  2. 修改视图配置,替换原有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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:57:16