【问题标题】:How to three-way many-to-many relationship in flask-sqlalchemy如何在flask-sqlalchemy中建立三向多对多关系
【发布时间】:2014-05-26 23:18:04
【问题描述】:

在flask-sqlalchemy中设计三路多对多的正确方法是什么?

假设我有用户、团队和角色。用户被分配到团队。分配给团队时,用户也会被分配到该团队中的角色。

from myapp import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), unique=True)

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<User(%s)>" % self.name

class Team(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), unique=True)

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<Team(%s)>" % self.name

class Role(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), unique=True)

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<Role(%s)>" % self.name

为此设计代理表的几种方法对我来说都失败了。我认为我误解了文档,因此不想让您与我迄今为止所采取的所有失败方法混淆。

我想留下一个问题:在 flask-sqlalchemy 中设计三向多对多关系的正确方法是什么。

【问题讨论】:

    标签: python orm sqlalchemy flask flask-sqlalchemy


    【解决方案1】:

    经过大量研究和挖掘,我似乎终于找到了答案。由于我发现许多其他人很难解决这个问题并且找不到完整而清晰的答案,我想我可以在这里发布它以供未来的旅行者使用。

    如果您遇到了这个问题,那么您可能并不是真的在寻找三向多对多。我以为我是,但我不是。

    回顾: 我有用户、团队和角色。如果用户加入团队,他也会被分配到该团队中的角色。

    我回到草稿板上,画出了我真正想要的东西:

    +---------+---------+---------+
    | user_id | team_id | role_id |
    +---------+---------+---------+
    |       1 |       1 |       1 |
    +---------+---------+---------+
    

    然后我开始明白,我并不是真的在寻找三路多对多,而是寻找与第四模型不同的三路一对多。

    class Membership(db.Model):
        user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
        team_id = db.Column(db.Integer, db.ForeignKey('team.id'), primary_key=True)
        role_id = db.Column(db.Integer, db.ForeignKey('role.id'), primary_key=True)
    
        db.UniqueConstraint('user_id', 'team_id', 'role_id')
        db.relationship('User', uselist=False, backref='memberships', lazy='dynamic')
        db.relationship('Team', uselist=False, backref='memberships', lazy='dynamic')
        db.relationship('Role', uselist=False, backref='memberships', lazy='dynamic')
    
        def __init__(self, user, team, role):
            self.user_id = user.id
            self.team_id = team.id
            self.role_id = role.id
    
        def __repr__(self):
            return "<Membership(%s)>"
    

    42 例:这正是我一直在寻找的答案 - 我刚刚问错了问题。

    【讨论】:

    • 有兴趣了解您如何在这种三元关系中添加/修改/删除项目
    • 我第二辆面包车的评论。我有同样的问题,很想知道添加/修改/删除查询。
    • 我认为 db.UniqueConstraint 不需要,因为 primary_key=True 已为所有列设置。
    • 这里也不需要显式定义 init。它与 db.Model 中的默认值相同。
    • @van 对于添加项目,它与任何其他表的正常情况相同(由于赞成票而响应,对于 necro 感到抱歉):aMembership = Membership(user=aUser, team=aTeam, role=aRole) 其中aUseraTeamaRole每个都只是各自类的一个实例。然后,您可以通过 aUser.memberships[i] 访问 Membership 对象。
    【解决方案2】:

    伙计们。有官方方法可以通过使用辅助表来解决两个多对多的问题。

    Helper_table = db.Table('Helper_table',
                         db.Column('id_a', db.Integer,
                                   db.ForeignKey('a.id')),
                         db.Column('id_b', db.Integer,
                                   db.ForeignKey('b.id'))
                    )
    
    class A(db.Model):  # A ORM
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(64), index=True, unique=True)
    
        bs = db.relationship(
            'B', secondary=Helper_table, lazy='dynamic')
    
        def __repr__(self):
            return '<A {}>'.format(self.username)
    
    class B(db.Model):  # B ORM
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(64), index=True, unique=True)
    
    
        as = db.relationship(
            'A', secondary=Helper_table, lazy='dynamic')
    
        def __repr__(self):
            return '<B {}>'.format(self.username)
    
    

    但它只能解决两个多对多的问题!!!它会自动处理关系。

    a1 = A(username="a1_"+str(uuid.uuid4()))
    b1 = B(username="b1_"+str(uuid.uuid4()))
    
    a1.bs.append(b1)
    db.session.add(a1)
    db.session.commit()
    
    

    正如上面的代码所示,它会自动将b1b1.as 添加到数据库中。

    但是当我在 3 many-many-many 情况下尝试这种方法时,一切都搞砸了。

    这是我问的问题:multi-helper table for many-many-many-... relationship in flask-sqlalchemy

    一般来说,我认为它应该是这个 repo 的一个特性。应该有一种优雅的方式来处理它。

    【讨论】:

      猜你喜欢
      • 2019-01-12
      • 1970-01-01
      • 2016-06-15
      • 2021-08-31
      • 1970-01-01
      • 2012-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多