基于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
相关产品推荐
相关产品推荐

