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

use*_*531 16 many-to-many sqlalchemy flask flask-sqlalchemy

Flask Mega教程中理解一些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
Run Code Online (Sandbox Code Playgroud)

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

三件事我不理解primaryjoinsecondaryjoin如下:

  1. 有什么目的primaryjoinsecondaryjoin检查的平等?或者,换句话说,究竟怎样完成primaryjoinsecondaryjoin添加user.ids到关联表?
  2. 由于双方primaryjoinsecondaryjoin采取了user.id要求,这user.id是哪儿的?
  3. 在我的follow/unfollow方法中,SQLAlchemy如何知道self是关注者,并且传入的用户是被关注者?

这些问题一直让我回到下一章,所以任何答案都非常感激.

Ped*_*eck 16

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

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

  3. 因为你要将它添加到self.followed集合中,告诉SQLAlchemy这是某人自己正在关注.如果你将它添加到self.followers集合中,你就会做反过来,告诉SQLAlchemy"用户"是自我的追随者.

参考:SQLAlchemy文档,用于指定备用连接条件(primaryjoinsecondaryjoin).