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

基于SQLAlchemy的食谱数据库设计及recipe_ingredient表数据插入咨询

关于SQLAlchemy食谱数据库设计与关联表数据插入的解决方案

先帮你梳理下当前设计的小问题,再一步步教你怎么往关联表插入数据~


一、先修正你的数据库设计

你当前把「用量、单位」放在ingredients表的思路不太合理哦!因为同一个食材(比如「水」)在不同食谱里的用量肯定不一样,这些属于食谱和食材之间的关联属性,应该放到中间关联表recipe_ingredient里,而ingredients表只需要存储食材的基础信息(比如唯一的食材名称)。这样能避免大量数据冗余,也更符合多对多关系的设计逻辑。

下面是修正后的SQLAlchemy模型代码:

方式1:把关联表定义为模型类(推荐,适合有额外字段的场景)

这种方式操作关联属性更直观,适合关联表有用量、单位这类额外字段的情况:

from sqlalchemy import Column, Integer, String, Float, ForeignKey
from sqlalchemy.orm import relationship, declarative_base

Base = declarative_base()

# 关联表模型:存储食谱与食材的关联关系+用量/单位
class RecipeIngredient(Base):
    __tablename__ = 'recipe_ingredient'
    recipe_id = Column(Integer, ForeignKey('recipes.id'), primary_key=True)
    ingredient_id = Column(Integer, ForeignKey('ingredients.id'), primary_key=True)
    quantity = Column(Float, nullable=False)  # 用量(如500)
    unit = Column(String(50), nullable=False)  # 单位(如ml/g)
    
    # 双向关联到Recipe和Ingredient
    recipe = relationship('Recipe', back_populates='ingredient_links')
    ingredient = relationship('Ingredient', back_populates='recipe_links')

class Recipe(Base):
    __tablename__ = 'recipes'
    id = Column(Integer, primary_key=True)
    name = Column(String(200), nullable=False)
    # 关联到中间表
    ingredient_links = relationship('RecipeIngredient', back_populates='recipe')

class Ingredient(Base):
    __tablename__ = 'ingredients'
    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False, unique=True)  # 如"水"、"面粉"
    # 关联到中间表
    recipe_links = relationship('RecipeIngredient', back_populates='ingredient')

方式2:把关联表定义为Table对象(适合无额外字段的场景)

如果后续关联表不需要额外字段,也可以用这种轻量化方式,但你当前的场景更推荐上面的模型类方式:

from sqlalchemy import Table

# 纯关联表(带额外字段)
recipe_ingredient = Table(
    'recipe_ingredient',
    Base.metadata,
    Column('recipe_id', Integer, ForeignKey('recipes.id'), primary_key=True),
    Column('ingredient_id', Integer, ForeignKey('ingredients.id'), primary_key=True),
    Column('quantity', Float, nullable=False),
    Column('unit', String(50), nullable=False)
)

# 调整Recipe和Ingredient的关系
class Recipe(Base):
    __tablename__ = 'recipes'
    id = Column(Integer, primary_key=True)
    name = Column(String(200), nullable=False)
    ingredients = relationship(
        'Ingredient',
        secondary=recipe_ingredient,
        back_populates='recipes'
    )

class Ingredient(Base):
    __tablename__ = 'ingredients'
    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False, unique=True)
    recipes = relationship(
        'Recipe',
        secondary=recipe_ingredient,
        back_populates='ingredients'
    )

二、向关联表插入数据的方法

根据你选择的关联表定义方式,插入数据的方法略有不同:

方法1:基于关联表模型类的插入(推荐)

这种方式最直观,直接创建RecipeIngredient对象来关联食谱和食材:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 初始化数据库连接和会话
engine = create_engine('sqlite:///recipes.db')  # 换成你的数据库URL
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# 1. 先创建并保存食材和食谱
water = Ingredient(name='水')
flour = Ingredient(name='面粉')
pancake = Recipe(name='家常煎饼')

session.add_all([water, flour, pancake])
session.commit()

# 2. 创建关联关系(带用量和单位)
pancake_water = RecipeIngredient(
    recipe=pancake,
    ingredient=water,
    quantity=200,
    unit='ml'
)
pancake_flour = RecipeIngredient(
    recipe=pancake,
    ingredient=flour,
    quantity=150,
    unit='g'
)

session.add_all([pancake_water, pancake_flour])
session.commit()

# 验证:查询煎饼的所有食材及用量
for link in pancake.ingredient_links:
    print(f"{link.ingredient.name}: {link.quantity}{link.unit}")

方法2:基于Table对象的插入

如果用的是纯Table关联表,可以通过session.execute直接执行插入语句:

# 假设已经创建并提交了pancake、water、flour对象
session.execute(
    recipe_ingredient.insert(),
    [
        {
            'recipe_id': pancake.id,
            'ingredient_id': water.id,
            'quantity': 200,
            'unit': 'ml'
        },
        {
            'recipe_id': pancake.id,
            'ingredient_id': flour.id,
            'quantity': 150,
            'unit': 'g'
        }
    ]
)
session.commit()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:43:21