2016-02-04 82 views
3

我有一个多客户平台,可以有多个标签的人,并让一个带有一个标签的foo对象。我不希望每个客户的用户与其他客户分享他们的联系人(个人)或标签或foo。每个客户的每个标签名称都是唯一的带复合键的sqlalchemy辅助表

我怎么能对标签(名称,CUSTOMER_NAME)一复合键和人员之间的N-M的关系和标签

我尝试这样做:

enter image description here

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的必须加载到前台网络,当我做session.merge()与标签(没有ID)我有:

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')] 

所以你会如何处理这种情况?

谢谢你的时间。


编辑: 万一它可以帮助时,布伦丹·阿贝尔响应,并显示代码后,我有这个错误:

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. 

我结束了(上添加人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']) 
         ) 

回答

2

你必须明确地表明,在使用一个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']) 
) 

docs提供了一些这方面的例子。

It’s important to note that the ForeignKeyConstraint is the only way to define a composite foreign key. While we could also have placed individual ForeignKey objects on both the invoice_item.invoice_id and invoice_item.ref_num columns, SQLAlchemy would not be aware that these two values should be paired together - it would be two individual foreign key constraints instead of a single composite foreign key referencing two columns.