Django Filters多值查询异常:vehicle_type参数拆分错误求助
问题:逗号分隔的查询参数无法正确过滤vehicle_type字段
问题场景
我想用逗号分隔的查询参数过滤vehicle_type字段,请求URL示例:
{{url}}/vehicles-records-info/75d9ee1b-8a03-4697-82e7-2d96ef0a8c2d/?vehicle_type=Mixer,Lorry
错误表现
打印生成的SQL查询时,得到的语句是:
... AND "vehicle_type" IN (M, i, x, e, r, ,, L, o, y))
预期结果
正确的SQL语句应为:
... AND "vehicle_type" IN ('Mixer', 'Lorry'))
当前使用的Filter代码
class VehicularAccessRecordInformationFilter(django_filters.FilterSet): vehicle_type = django_filters.CharFilter(field_name='vehicle_type', lookup_expr='in') start_timestamp = django_filters.DateTimeFilter(field_name='timestamp', lookup_expr='gte') end_timestamp = django_filters.DateTimeFilter(field_name='timestamp', lookup_expr='lte') class Meta: model = VehicleAccessRecordInformation fields = ['vehicle_type', 'timestamp']
解决方案
问题核心是CharFilter会把传入的字符串当作单个值处理,而in查询需要的是列表格式。以下两种方法可解决:
方法1:自定义过滤器处理逻辑
重写filter方法,将逗号分隔的参数拆分为列表:
class VehicularAccessRecordInformationFilter(django_filters.FilterSet): vehicle_type = django_filters.CharFilter(field_name='vehicle_type', method='filter_vehicle_type') start_timestamp = django_filters.DateTimeFilter(field_name='timestamp', lookup_expr='gte') end_timestamp = django_filters.DateTimeFilter(field_name='timestamp', lookup_expr='lte') def filter_vehicle_type(self, queryset, name, value): # 拆分参数并去除空值 values = [v.strip() for v in value.split(',') if v.strip()] if values: return queryset.filter(**{f'{name}__in': values}) return queryset class Meta: model = VehicleAccessRecordInformation fields = ['vehicle_type', 'timestamp']
方法2:使用django-filter内置的In过滤器
继承BaseInFilter和CharFilter,直接实现列表参数处理:
from django_filters import BaseInFilter, CharFilter class CharInFilter(BaseInFilter, CharFilter): pass class VehicularAccessRecordInformationFilter(django_filters.FilterSet): vehicle_type = CharInFilter(field_name='vehicle_type', lookup_expr='in') start_timestamp = django_filters.DateTimeFilter(field_name='timestamp', lookup_expr='gte') end_timestamp = django_filters.DateTimeFilter(field_name='timestamp', lookup_expr='lte') class Meta: model = VehicleAccessRecordInformation fields = ['vehicle_type', 'timestamp']
两种方法都能将vehicle_type=Mixer,Lorry解析为['Mixer', 'Lorry'],生成符合预期的SQL语句。
内容的提问来源于stack exchange,提问作者user7104332
相关产品推荐
相关产品推荐

