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

Django-filter结合DRF同字段多值查询如何实现OR逻辑?

错误原因

你自定义的MultiValueCharFilter类没有声明接收conjoined参数,也没有内置对应的多条件拼接逻辑,因此传入该参数会直接触发初始化参数异常。你当前循环调用super().filter()的写法默认就是AND逻辑,要实现OR查询需要手动调整过滤器逻辑,引入Q对象拼接查询条件。

完整实现代码

首先导入Django的Q对象,然后修改自定义过滤器类,增加conjoined参数支持和对应逻辑:

from rest_framework import viewsets
from django_filters import rest_framework as filters
from django.db.models import Q
from .serializers import BookInfoSerializer
from .models import BookInfo


class MultiValueCharFilter(filters.BaseCSVFilter, filters.CharFilter):
    def __init__(self, *args, **kwargs):
        # 新增conjoined参数,默认True为AND逻辑,False为OR逻辑
        self.conjoined = kwargs.pop('conjoined', True)
        super().__init__(*args, **kwargs)

    def filter(self, qs, value):
        values = value or []
        if not values:
            return qs
        
        # AND逻辑:和原有实现保持一致
        if self.conjoined:
            for v in values:
                qs = super().filter(qs, v)
            return qs
        
        # OR逻辑:用Q对象拼接所有查询条件
        q = Q()
        lookup = f"{self.field_name}__{self.lookup_expr}"
        for v in values:
            q |= Q(**{lookup: v})
        return qs.filter(q)


class BookInfoFilter(filters.FilterSet):
    # 传入conjoined=False即可实现同一字段多关键词OR查询
    title = MultiValueCharFilter(lookup_expr='contains', conjoined=False)

    class Meta:
        model = BookInfo
        fields = ['title']


class BookInfoAPIView(viewsets.ReadOnlyModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
    filter_class = BookInfoFilter

使用方式

请求时传入逗号分隔的多个关键词即可,示例请求参数:
?title=张三,李四
返回结果为标题包含张三 或者 包含李四的所有书籍数据。
如果需要恢复AND逻辑,只需将conjoined参数改为True或者去掉该参数即可。

内容的提问来源于stack exchange,提问作者Tio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 12:24:02