我有一个多客户平台,可以有几个标签的人,并说一个带有一个标签的foo对象。我不希望每个客户的用户与其他客户分享他们的联系人(人)或标签或foo。每个标签名称对每个客户都是唯一的。
我如何才能拥有标签的复合键(name,customer_name)以及人与标签之间的 n-m关系?
我试过了:
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加载到前端网络上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')]
所以你会如何处理这个案子?
感谢您的时间。
编辑 : 为了防止在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'])
)
答案 0 :(得分: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提供了一些例子。
重要的是要注意
ForeignKeyConstraint
是唯一的方法 定义复合外键。虽然我们也可以放置 invoice_item.invoice_id和。上的各个ForeignKey对象 invoice_item.ref_num列,SQLAlchemy不会意识到这些 两个值应该配对在一起 - 它将是两个人 外键约束而不是单个复合外键 引用两列。