我正在使用Association Proxy设置间接的多对多关系,其中Submission
可以包含多个Role
,而Role
可以是与多个Submission
相关联。请注意,我还使用flask-sqlalchemy
。
class Role(db.Model):
__tablename__ = 'role'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text)
def __init__(self, name):
self.name = name
class Submission(db.Model):
__tablename__ = 'submission'
id = db.Column(db.Integer, primary_key=True)
submission_to_role = relationship("SubmissionToRole", cascade="all, delete-orphan")
roles = association_proxy('submission_to_role', 'role')
class SubmissionToRole(db.Model):
__tablename__ = 'submission_to_role'
submission_id = db.Column(db.Integer, db.ForeignKey('submission.id', ondelete='CASCADE'), primary_key=True)
role_id = db.Column(db.Integer, db.ForeignKey('role.id', ondelete='CASCADE'), primary_key=True)
submission = relationship(Submission)
role = relationship(Role)
def __init__(self, role):
self.role = role
我需要这样的行为:
submission = Submission()
role_a = Role('Backend Developer')
role_b = Role('Frontend Developer')
db.session.add(submission)
db.session.add(role_a)
db.session.add(role_b)
db.session.commit()
submission.roles.append(role_a) # submission.roles length should become 1
submission.roles.append(role_b) # submission.roles length should become 2
submission.roles.append(role_a) # submission.roles length should remain 2, since I already associated role_a previously.
但是,当我关联已经关联的Role
时,SQLAlchemy会创建一个重复的关联对象。
我如何实现我想要的行为?我写了一个Submission
的函数来解决它
def associate_role(self, role):
assoc_model = SubmissionToRole.query.filter(
SubmissionToRole.submission_id == self.id
).filter(
SubmissionToRole.role_id == role.id
).first()
if not assoc_model:
self.roles.append(role)
但想要更清洁,更容易重复使用的东西。我可以使用SQLAlchemy原生的东西吗?
答案 0 :(得分:0)
您可以在 SubmissionToRole
上创建一个 UniqueConstraint,这让您可以指定多对多表将分别具有 Role
和 Submission
的重复值,Role
和 Submission
值的 pairings 不应重复。这称为复合唯一约束。
from sqlalchemy import UniqueConstraint
class SubmissionToRole(db.Model):
__tablename__ = 'submission_to_role'
submission_id = db.Column(db.Integer, db.ForeignKey('submission.id', ondelete='CASCADE'), primary_key=True)
role_id = db.Column(db.Integer, db.ForeignKey('role.id', ondelete='CASCADE'), primary_key=True)
submission = relationship(Submission)
role = relationship(Role)
def __init__(self, role):
self.role = role
# explicit/composite unique constraint. 'name' is optional.
__table_args__ = (UniqueConstraint('submission', 'role', name='submission_role_uc'),
)