难以理解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
因此,我理解,因为这是一种自引用关系,所以我们需要某种方式让关联表确定表中的哪个User是关注者,表中的哪个User是跟随者。
Primaryjoin
和secondaryjoin
完成此操作,但是如何?关于
primaryjoin
和secondaryjoin
我不了解的三件事如下:primaryjoin
和secondaryjoin
检查相等性的目的是什么?或者,换句话说,primaryjoin
和secondaryjoin
如何将user.id
添加到关联表中?由于
primaryjoin
和secondaryjoin
都具有user.id
要求,因此哪个user.id
会去哪里?在我的关注/取消关注方法中,SQLAlchemy如何知道自我是关注者,而传入的用户是关注者?
这些问题一直使我无法进入下一章,因此,任何答案都非常感谢。
最佳答案
在多对多关系中,primaryjoin表达式描述了左表和联结表之间的联接,secondaryjoin描述了联结表和右表之间的联接。换句话说,primaryjoin表达式说:“在followers_id为X的followers表中查找所有行”,secondaryjoin表达式说“在followed_id为X的followers表中查找所有行”,然后将这两行一起查找跟随用户X的所有用户,以及跟随用户X的所有用户。
这取决于您查询的方向。当您请求user.followers时,它将通过使用primaryjoin来查询followers表中的followed_id == user.id的所有行,并使用other.id == follower_id来检索其他用户。当您要求user.followed时,它将使用secondaryjoin在followers表中查询follower_id == user.id的所有行,并使用other.id == followed_id检索其他用户。
因为您要将其添加到self.followed集合中,所以告诉SQLAlchemy自我跟踪的人。如果将其添加到self.followers集合中,您将做相反的事情,告诉SQLAlchemy'user'是self的跟随者。
参考:SQLAlchemy documentation for specifying alternative join conditions(primaryjoin
和secondaryjoin
)。