簡體   English   中英

sqlalchemy輔助表與復合鍵

[英]sqlalchemy secondary table with compound keys

我有一個多客戶平台,可以有幾個標簽的人,並說一個帶有一個標簽的foo對象。 我不希望每個客戶的用戶與其他客戶分享他們的聯系人(人)或標簽或foo。 每個標簽名稱對每個客戶都是唯一的

我怎么能有標簽 (name,customer_name)的復合鍵人與標簽之間nm關系

我試過這個:

在此輸入圖像描述

person_label_table = Table('person_label', Base.metadata,
                       Column('person_id', Integer, ForeignKey('person.id'), primary_key=True),
                       Column('name', Unicode(32), ForeignKey('label.name'), primary_key=True),
                       Column('customer_name', String(32), ForeignKey('label.customer_name'), primary_key=True)
                       )

class Person(Base, SaveMixin):
    __tablename__ = 'person'
    id = Column(Integer, primary_key=True)
    labels = relationship('Label', secondary=person_label_table)

class Label(Base, SaveMixin):
    __tablename__ = 'label'
    name = Column(Unicode(32), primary_key=True)
    customer_name = Column(String(32), ForeignKey('customer.name'), primary_key=True)
    color = Column(String(32))

但我有這個錯誤:

sqlalchemy.exc.AmbiguousForeignKeysError: Can't determine join between 'label' and 'person_label'; tables have more than one foreign key constraint relationship between them. Please specify the 'onclause' of this join explicitly.

我還嘗試使用更經典的鏈接表person_label(label_id,person_id)並在標簽中添加id,但是當我使用標簽(沒有id)執行session.merge()時,必須將標簽ID加載到前端Web上有:

sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: label.name, label.customer_name [SQL: 'INSERT INTO label (name, customer_name, color) VALUES (?, ?, ?)'] [parameters: ('foo', 'bar', 'grey')]

你怎么處理這個案子呢?

感謝您的時間。


編輯 :以防萬一它可以幫助,在Brendan Abel響應和顯示的代碼后,我有這個錯誤:

sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship Person.labels - there are multiple foreign key paths linking the tables via secondary table 'person_label'.  Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference from the secondary table to each of the parent and child tables.

所以我親自更改了標簽的定義:

labels = relationship('Label', secondary=person_label_table, foreign_keys=[id]):

但那時我有:

sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Person.labels - there are no foreign keys linking these tables via secondary table 'person_label'.  Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify 'primaryjoin' and 'secondaryjoin' expressions.

我最終得到了(在person上添加了primaryjoin / secondaryjoin並刪除了復合鍵上的ForeignKey):

class Person(Base, SaveMixin):
    __tablename__ = 'person'
    labels = relationship('Label', secondary=person_label_table,
                      primaryjoin='and_(Person.id == person_label.c.person_id)',
                      secondaryjoin='and_(person_label.c.name == Label.name, person_label.c.customer_name == Label.customer_name)')

person_label_table = Table('person_label', Base.metadata,
                       Column('person_id', Integer, ForeignKey('person.id'), primary_key=True),
                       Column('name', Unicode(32), primary_key=True),
                       Column('customer_name', String(32), primary_key=True),
                       ForeignKeyConstraint(['name', 'customer_name'], ['label.name', 'label.customer_name'])
                       )

您必須使用ForeignKeyConstraint顯式指示復合關系:

person_label_table = Table('person_label', Base.metadata,
    Column('person_id', Integer, ForeignKey('person.id'), primary_key=True),
    Column('name', Unicode(32), primary_key=True),
    Column('customer_name', String(32), primary_key=True),
    ForeignKeyConstraint(['name', 'customer_name'], ['label.name', 'label.customer_name'])
)

文檔提供了一些這方面的例子。

值得注意的是, ForeignKeyConstraint是定義復合外鍵的唯一方法。 雖然我們也可以在invoice_item.invoice_id和invoice_item.ref_num列上放置單獨的ForeignKey對象,但SQLAlchemy不會意識到這兩個值應該配對在一起 - 它將是兩個單獨的外鍵約束而不是單個復合外鍵引用兩列。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM