在DRF中使用django-filter遇到的两个过滤问题求助
Django Filter 问题解决:空参数兼容与逗号分隔多品牌过滤
问题说明
- 传入空的
brand_name参数(如?brand_name=)时,会触发验证错误,提示“Select a valid choice. is not one of the available choices.” - 当前多品牌过滤需要重复传递
brand_name参数(如?brand_name=nike&brand_name=guchi),希望改为逗号分隔形式(如?brand_name=nike,guchi)
解决方案
1. 修正模型拼写错误
首先修正models.py中Product类的字段拼写错误:
# models.py 修正后 brand_name = models.ForeignKey(Brand, on_delete=models.CASCADE) # 注意ForeignKey首字母大写
2. 自定义Filter处理空参数与逗号分隔
修改views.py,自定义过滤类实现需求:
# views.py 修改后 import django_filters from django_filters import filters from rest_framework import generics from .models import Product, Brand from .serializers import ProductSerializer class BrandNameFilter(filters.BaseFilter): def filter(self, qs, value): # 空值直接返回原查询集,避免报错 if not value: return qs # 拆分逗号分隔的品牌名,去除空格 brand_names = [name.strip() for name in value.split(',')] # 查询对应品牌实例,过滤产品 brands = Brand.objects.filter(name__in=brand_names) return qs.filter(brand_name__in=brands) class ProductFilter(filters.FilterSet): brand_name = BrandNameFilter() class Meta: model = Product fields = ["has_discount", "brand_name", "available"] class filtered_data(generics.ListAPIView): authentication_classes = [] permission_classes = [] queryset = Product.objects.all() serializer_class = ProductSerializer filterset_class = ProductFilter
代码说明
- BrandNameFilter类:
- 继承
filters.BaseFilter,重写filter方法实现自定义逻辑 - 空值处理:参数为空时直接返回原查询集,跳过过滤逻辑
- 逗号分隔解析:将传入的字符串按逗号拆分,去除每个品牌名的空格,查询对应品牌后过滤关联产品
- 继承
- ProductFilter:用自定义过滤类替换原有的
ModelMultipleChoiceFilter,摆脱默认的多选参数验证限制
测试验证
- 空参数:访问
http://127.0.0.1:8000/api/products/filtered_data/?brand_name=,不再报错,返回全部产品 - 多品牌逗号分隔:访问
http://127.0.0.1:8000/api/products/filtered_data/?brand_name=nike,guchi,返回指定品牌的产品 - 单品牌:访问
http://127.0.0.1:8000/api/products/filtered_data/?brand_name=nike,正常返回对应品牌产品 - 组合过滤:访问
http://127.0.0.1:8000/api/products/filtered_data/?brand_name=nike,guchi&has_discount=true,返回符合组合条件的产品
内容的提问来源于stack exchange,提问作者coder
相关产品推荐
相关产品推荐

