Django带through的ManyToMany关系如何反向查询关联模型及中间表数据
解决方案
你需要调整序列化器结构,新增适配Product查询场景的中间表序列化器,再在Product序列化器中引入关联字段即可,具体修改如下:
步骤1:调整中间表序列化器(可选新增,避免和原有Recipe侧的序列化逻辑冲突)
原有RecipeInputSerializer是为Recipe查询场景设计的,仅返回Product关联信息,我们新增一个适配Product查询场景的版本,返回关联的Recipe信息:
# serializers.py 新增如下代码 class RecipeInputForProductSerializer(serializers.HyperlinkedModelSerializer): # 按需添加你需要返回的Recipe字段,以下为示例 recipe_id = serializers.ReadOnlyField(source='recipe.id') recipe_name = serializers.ReadOnlyField(source='recipe.name') # 如果需要返回完整的Recipe信息,可以直接嵌套RecipeSerializer: # recipe = RecipeSerializer(read_only=True) class Meta: model = RecipeInput fields = ("recipe_id", "recipe_name", "amount")
步骤2:修改ProductSerializer添加关联字段
通过Product反向关联的中间表集合,加载关联的Recipe和中间表信息:
class ProductSerializer(serializers.ModelSerializer): # recipeinput_set是Django默认生成的反向外键关联名,many=True表示对应多条中间表记录 used_in_recipes = RecipeInputForProductSerializer(source='recipeinput_set', many=True, read_only=True) class Meta: model = Product fields = "__all__" depth = 3
可选优化项
优化1:语义化反向关联名
如果觉得默认的recipeinput_set命名不够清晰,可以修改中间表的外键定义,自定义关联名:
# models.py 修改RecipeInput的product外键 class RecipeInput(models.Model): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) # 新增related_name定义 product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='recipe_inputs') amount = models.IntegerField()
修改后ProductSerializer的关联字段可以改为:
used_in_recipes = RecipeInputForProductSerializer(source='recipe_inputs', many=True, read_only=True)
优化2:解决N+1查询问题
在视图中查询Product时使用prefetch_related预加载关联数据,提升查询性能:
# 示例视图的查询集写法 queryset = Product.objects.all().prefetch_related('recipe_inputs__recipe')
内容的提问来源于stack exchange,提问作者Eric Jansen
相关产品推荐
相关产品推荐

