You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:18:02