'primaryjoin'和'secondaryjoin'如何在SQLAlchemy中为多对多关系工作?

时间:2013-10-25 20:06:31

标签: flask sqlalchemy many-to-many flask-sqlalchemy

Flask Mega Tutorial了解一些Flask-SQLAlchemy内容有些困难。这是代码:

followers = db.Table('followers',
    db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
)

class User(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    nickname = db.Column(db.String(64), unique = True)
    email = db.Column(db.String(120), index = True, unique = True)
    role = db.Column(db.SmallInteger, default = ROLE_USER)
    posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
    about_me = db.Column(db.String(140))
    last_seen = db.Column(db.DateTime)
    followed = db.relationship('User', 
        secondary = followers, 
        primaryjoin = (followers.c.follower_id == id), 
        secondaryjoin = (followers.c.followed_id == id), 
        backref = db.backref('followers', lazy = 'dynamic'), 
        lazy = 'dynamic')

    def follow(self, user):
        if not self.is_following(user):
            self.followed.append(user)
            return self

    def unfollow(self, user):
        if self.is_following(user):
            self.followed.remove(user)
            return self

    def is_following(self, user):
        return self.followed.filter(followers.c.followed_id == user.id).count() > 0

所以我理解,因为这是一个自引用关系,我们需要一些方法让关联表找出表中哪个用户是跟随者,以及表中哪个用户是被跟踪的用户。 Primaryjoinsecondaryjoin完成此任务,但如何实现?

我对primaryjoinsecondaryjoin无法理解的三件事情如下:

  1. primaryjoinsecondaryjoin检查平等的目的是什么?或者,换句话说,primaryjoinsecondaryjoin如何将user.id添加到关联表中?
  2. 由于primaryjoinsecondaryjoin都要求user.iduser.id会去哪里?
  3. 在我的follow / unfollow方法中,SQLAlchemy如何知道self是关注者,并且传入的用户是被关注者?
  4. 这些问题一直让我回到下一章,所以任何答案都非常感激。

1 个答案:

答案 0 :(得分:14)

  1. 在多对多关系中,primaryjoin表达式描述左表和联结表之间的连接,而secondaryjoin描述联结表和右表之间的连接。换句话说,primaryjoin表达式是,"查找followers表中follower_id为X"的所有行,secondaryjoin表达式说"查找followers表中follow_id为X&#的所有行34;,并将这两者结合起来找到跟随用户X的所有用户,以及用户X后面跟随的所有用户。

  2. 这取决于您查询的方向。当您请求user.followers时,它会通过使用primaryjoin查询followers表以查找follow_id == user.id的所有行,并使用other.id == follower_id检索其他用户。当您请求user.followed时,它使用secondaryjoin在followers表中查询follower_id == user.id的所有行,并使用other.id == follow_id检索其他用户。

  3. 因为您将其添加到self.followed集合中,告诉SQLAlchemy有人自己正在关注。如果你将它添加到self.followers集合中,你就会做反过来,告诉SQLAlchemy那个用户'是自我的追随者。

  4. 参考:SQLAlchemy documentation for specifying alternative join conditionsprimaryjoinsecondaryjoin)。