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

Django中如何正确实现食谱与食材的一对多关联?

解决Django中Recipe与Ingredient的一对多关系问题

嘿,你现在的问题核心是ForeignKey的位置放反了!你想要的是「一个食谱对应多个食材」的一对多关系,这时候ForeignKey应该定义在多的那一端(也就是Ingredient模型),而不是Recipe模型里。

一、修正模型结构

当前你的Recipe模型里的ingredients字段是ForeignKey,这会变成「多个食谱对应同一个食材」的多对一关系,刚好和你的需求相反。我们把ForeignKey移到Ingredient模型,指向Recipe:

from django.db import models

class Recipe(models.Model):
    title = models.CharField(max_length=120)
    preparation = models.TextField(default='Here comes the preparation...')  # 帮你修正了拼写错误哦

    def __str__(self):
        return self.title  # 方便在后台和shell里快速识别对象

class Ingredient(models.Model):
    ingredient_title = models.CharField(max_length=120)
    amount = models.IntegerField()
    unit = models.CharField(max_length=10)
    recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, related_name="ingredients")
    # 设置related_name后,你可以直接用recipe.ingredients访问关联食材,不用默认的ingredient_set

    def __str__(self):
        return f"{self.amount}{self.unit} {self.ingredient_title}"

二、执行数据库迁移

修改完模型后,需要更新数据库结构:

python manage.py makemigrations
python manage.py migrate

三、在Shell中创建实例

现在你可以先创建Recipe,再给它绑定多个Ingredient了:

# 1. 先创建一个食谱对象
recipe = Recipe.objects.create(title='Essen1', preparation='prep1')

# 2. 给这个食谱添加单个食材
Ingredient.objects.create(ingredient_title="ZutatTitel1", amount=2, unit='g', recipe=recipe)
Ingredient.objects.create(ingredient_title="ZutatTitel2", amount=5, unit='ml', recipe=recipe)

# 3. 或者批量添加食材
ingredient1 = Ingredient(ingredient_title="ZutatTitel3", amount=1, unit='piece')
ingredient2 = Ingredient(ingredient_title="ZutatTitel4", amount=300, unit='g')
recipe.ingredients.add(ingredient1, ingredient2)  # 得益于我们设置的related_name

四、优化后台管理页面

为了在Django Admin里能直接编辑食谱的所有食材(不用跳转到Ingredient单独页面),可以配置Inline组件:

在admin.py里添加:

from django.contrib import admin
from .models import Recipe, Ingredient

class IngredientInline(admin.TabularInline):
    model = Ingredient
    extra = 3  # 默认显示3个空的食材输入框,方便批量添加

class RecipeAdmin(admin.ModelAdmin):
    inlines = [IngredientInline]

admin.site.register(Recipe, RecipeAdmin)
admin.site.register(Ingredient)

现在进入Recipe的后台编辑页面,就能直接添加、修改多个食材了,不用再只能选一个!

五、访问关联数据

  • 获取某个食谱的所有食材:recipe.ingredients.all()(因为设置了related_name)
  • 获取某个食材所属的食谱:ingredient.recipe

内容的提问来源于stack exchange,提问作者Frederick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:53:10