Django多对多关联下按Variant的ID过滤Category关联数据问题
问题原因分析
- 之前
TypeError: 'int' object is not iterable报错是因为__in查询要求传入列表/元组等可迭代对象,你传入了单个int类型的variant_id,语法不合法。 - 你在Category的查询集上加variant过滤逻辑,仅能筛选出「关联了指定variant的分类」,不会对分类下关联的variant子集做过滤,所以序列化后依然会返回分类下所有variant。
解决步骤
需要同时调整视图层和序列化层代码,逻辑如下:
- 视图层拿到请求传入的variant_id后,传入序列化器的上下文参数,供序列化层动态过滤使用
- 序列化层通过
SerializerMethodField自定义variant字段的返回逻辑,根据传入的variant_id决定返回单个对象还是全部数组
修正后代码
视图层(VIEW.PY)
def retrieve(self, request, pk=None): # 适配GET/POST请求的参数获取 variant_id = request.data.get('variant_id') or request.query_params.get('variant_id') # retrieve方法返回单个分类对象,不需要many=True category = Category.objects.get(category_id=pk) # 将variant_id传入序列化器上下文 serializer = CategoryServiceListSerializer(category, context={"variant_id": variant_id}) # 直接返回序列化结果即可 return Response(serializer.data)
序列化层(SERIALIZER.PY)
class CategoryServiceListSerializer(serializers.ModelSerializer): # 自定义variant字段的生成逻辑 variant = serializers.SerializerMethodField() class Meta: fields = "__all__" model = Category def get_variant(self, obj): variant_id = self.context.get("variant_id") if variant_id: # 传入了variant_id则过滤返回单个匹配的variant对象 target_variant = obj.variant_set.filter(variant_id=variant_id).first() return VariantServiceSerializer(target_variant).data # 未传variant_id则返回全量variant数组,兼容原有逻辑 return VariantServiceSerializer(obj.variant_set.all(), many=True).data class VariantServiceSerializer(serializers.ModelSerializer): class Meta: model = Variant fields = "__all__"
补充说明
如果需要兼容多个variant_id的传入场景,可以将参数改为数组格式,调整过滤逻辑为__in即可:
# 示例:传入variant_id数组时的逻辑 variant_ids = request.data.get("variant_ids", []) target_variants = obj.variant_set.filter(variant_id__in=variant_ids)
内容的提问来源于stack exchange,提问作者Ajay Chaurasia
相关产品推荐
相关产品推荐

