使用DjangoFilter过滤SerializerMethodField字段时报错:True不是有效字段
问题原因
你用SerializerMethodField定义的is_favorited是序列化阶段动态计算的字段,不属于Recipe模型的数据库字段,DjangoFilterBackend默认只能基于模型实际存在的字段做过滤,所以直接在filterset_fields里加这个字段会报错。
解决方法
需要自定义FilterSet类,手动实现is_favorited的过滤逻辑,步骤如下:
1. 自定义RecipeFilter类
在你的app下新建或修改filters.py,写入以下代码:
from django_filters import rest_framework as filters from .models import Recipe, Favorite class RecipeFilter(filters.FilterSet): is_favorited = filters.BooleanFilter(method='filter_is_favorited') def filter_is_favorited(self, queryset, name, value): user = self.request.user # 匿名用户无收藏数据,直接返回空集合 if user.is_anonymous: return queryset.none() # 提取当前用户收藏的所有食谱ID favorited_ids = Favorite.objects.filter(user=user).values_list('recipe_id', flat=True) if value: # 过滤出已收藏的食谱 return queryset.filter(id__in=favorited_ids) else: # 过滤出未收藏的食谱 return queryset.exclude(id__in=favorited_ids) class Meta: model = Recipe fields = ['is_favorited'] # 可添加其他需要过滤的模型字段
2. 修改视图集配置
把原来的filterset_fields替换为自定义的filterset_class:
from .filters import RecipeFilter class RecipeViewSet(viewsets.ModelViewSet): queryset = Recipe.objects.all() serializer_class = RecipeSerializer # 替换为你的序列化器类 filter_backends = [filters.DjangoFilterBackend] filterset_class = RecipeFilter # 指定自定义FilterSet
3. 验证过滤效果
现在在Postman中可以正常使用参数过滤:
?is_favorited=true:返回当前用户已收藏的食谱?is_favorited=false:返回当前用户未收藏的食谱- 匿名用户请求任意
is_favorited参数都会返回空集合,和序列化器逻辑一致
内容的提问来源于stack exchange,提问作者aleksander
相关产品推荐
相关产品推荐

