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
相关产品推荐
相关产品推荐

