2014-06-26 66 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