2014-06-26 63 views
3

我在设置两个模型之间的多个关系时遇到问题。这是我的两个车型,因为我现在有他们:两个表之间的flask-sqlalchemy多种关系类型

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

是的,我认为这有一个更好的解决方案... – cyberra

回答

2

这里有两个圆形的依赖关系:

  1. 的外键是互相依赖于每个表的存在。必须在依赖表已存在之后创建其中一个fks。将use_alter=Truename='some_name设置为一个来解决此问题。
  2. 这两个关系都需要在插入后解析其目标的primary_key,但是两者之间相互依赖于已经被提交。将其设置为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 
+0

[吉斯特与瓶-SQLAlchemy的和烧瓶管理](https://gist.github.com/cyrexcyborg/e99c114a5b33cd2da538) – cyberra

+0

我很喜欢这解决方案,但可以添加另一个Class(User)?,这样我就可以轻松获得属于产品许多图像之一的所有用户(比方说)的图像。我试图建立一个系统,允许用户评价属于产品的图像。 – sb32134

+0

@davidism真棒,几乎是我在找的东西。如果封面图像是分开的,这也是有效的,即不是图像集合的一部分? – Lukas