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

Django的models.py中如何配置实现菜品关联多个配方所需食材

Django餐厅管理系统菜谱多食材关联配置方案

你的场景需要使用带额外字段的多对多关联(因为每个食材对应菜谱需要存储用量,不能用默认的无字段多对多中间表),你原本设计的RecipeRequirement就是用来做中间关联表的,只需调整字段关联即可:

1. 修正models.py代码

from django.db import models

# Create your models here.
    
class Ingredient(models.Model):
    name = models.CharField(max_length=35)
    quantity = models.IntegerField()
    unit = models.CharField(max_length=5)
    unit_price = models.FloatField()

    def __str__(self):
        return self.name

class MenuItem(models.Model):
    title = models.CharField(max_length=35)
    price = models.FloatField()
    example = models.ImageField()
    # 配置多对多关联,指定通过RecipeRequirement中间表建立关联
    ingredients = models.ManyToManyField(Ingredient, through="RecipeRequirement", related_name="menu_items")

    def __str__(self):
        return self.title

class RecipeRequirement(models.Model):
    menu_item = models.ForeignKey(MenuItem, default = 1,  on_delete=models.SET_DEFAULT)
    # 原CharField改为外键关联Ingredient表,而非直接存食材名字符串
    ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
    quantity = models.FloatField()
    def __str__(self):
        return f"{self.menu_item.title} - {self.ingredient.name}"

class Purchase(models.Model):
    menu_item = models.ForeignKey(MenuItem, default=1, on_delete=models.SET_DEFAULT)
    timestamp = models.DateTimeField()

    def __str__(self):
        return 'Purchase ' + str(self.menu_item) + str(self.timestamp)

2. 异常现象说明

你之前遇到的「新增食材自动出现在所有菜品的关联食材列表」是Django admin的默认展示逻辑:多对多选择框会默认列出所有Ingredient表中的记录作为可选项,未手动勾选的食材不会真的和当前菜品建立关联,属于展示逻辑而非实际数据绑定问题。

3. 优化Admin配置(可选)

如果要直接在菜品编辑页新增/编辑对应食材和用量,不需要手动选多对多选项,可以在admin.py中配置行内关联:

from django.contrib import admin
from .models import Ingredient, MenuItem, RecipeRequirement, Purchase

class RecipeRequirementInline(admin.TabularInline):
    model = RecipeRequirement
    extra = 1 # 新增菜品时默认预留1个食材录入位

@admin.register(MenuItem)
class MenuItemAdmin(admin.ModelAdmin):
    inlines = [RecipeRequirementInline]
    exclude = ("ingredients",) # 隐藏默认的多对多选择框,避免混淆

admin.site.register(Ingredient)
admin.site.register(RecipeRequirement)
admin.site.register(Purchase)

配置完成后执行makemigrations和migrate命令同步数据库结构即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 07:09:00