如何在flask-sqlalchemy中实现三方多对多的关系

时间:2014-04-12 20:20:13

标签: python orm sqlalchemy flask flask-sqlalchemy

在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中设计一个三向多对多关系的正确方法是什么。

2 个答案:

答案 0 :(得分:13)

经过大量的研究和挖掘,我终于找到了答案。由于我发现很多其他人很难解决这个问题并且无法找到完整而明确的答案,我想我可以在这里发布给未来的旅行者。

如果您遇到过这个问题,那么您可能无法真正寻找三对多对多的问题。我以为我是,但我不是。

<强>回顾: 我有用户,团队和角色。如果用户加入团队,他也会在该团队中分配一个角色。

我回到了刮板,画了我真正想要的东西:

+---------+---------+---------+
| 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:这正是我一直在寻找的答案 - 我刚刚提出了错误的问题。

答案 1 :(得分:1)

老兄。有两种使用帮助器表解决许多问题的官方方法。

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个很多很多情况下尝试此方法时,一切都会恢复正常。

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

通常,我认为这应该是此回购协议的功能。应该有一种优雅的处理方式。