我在两个模型之间设置多个关系时遇到问题。这些是我现在拥有的两个模型:
class Product(db.Model):
tablename='product'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
image_id = db.Column(db.Integer, db.ForeignKey('image.id'))
image = db.relationship('Image',uselist=False,backref=db.backref('product'))
class Image(db.Model):
__tablename__='address'
id = db.Column(db.Integer, primary_key=True)
normal = db.Column(db.String(200))
product_id = db.Column(db.Integer, db.ForeignKey('product.id'))
product = db.relationship('Product', backref='product_images')
产品应该与封面图像一对一,以及与其他图像库一对一的产品。但是,外键存在循环依赖。
我只想在两张表中这样做。还有另一种方法可以实现这两种关系吗?
此时代码抛出:
sqlalchemy.exc.AmbiguousForeignKeysError
答案 0 :(得分:2)
这里有两个循环依赖:
use_alter=True
和name='some_name
即可解决此问题。post_update=True
设置为一个即可解决此问题。请参阅以下文档:
这是一个展示解决方案的工作示例。
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base(bind=engine)
class Product(Base):
__tablename__ = 'product'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
# cover image foreign key
# use_alter=True along with name='' adds this foreign key after Image has been created to avoid circular dependency
cover_id = Column(Integer, ForeignKey('image.id', use_alter=True, name='fk_product_cover_id'))
# cover image one-to-one relationship
# set post_update=True to avoid circular dependency during
cover = relationship('Image', foreign_keys=cover_id, post_update=True)
class Image(Base):
__tablename__ = 'image'
id = Column(Integer, primary_key=True)
path = Column(String, nullable=False)
product_id = Column(Integer, ForeignKey(Product.id))
# product gallery many-to-one
product = relationship(Product, foreign_keys=product_id, backref='images')
# nothing special was need in Image, all circular dependencies were solved in Product
Base.metadata.create_all()
# create some images
i1 = Image(path='img1')
i2 = Image(path='img2')
i3 = Image(path='img3')
i4 = Image(path='img4')
# create a product with those images, one of which will also be the cover
p1 = Product(name='sample', images=[i1, i2, i3, i4], cover=i2)
session.add(p1)
session.commit()
print 'cover:', p1.cover.path # prints one cover image path
print 'images:', [i.path for i in p1.images] # prints 4 gallery image paths
print 'image product:', p1.images[0].product.name # prints product name from image perspective