【问题标题】:How do 'primaryjoin' and 'secondaryjoin' work for many-to-many relationship in SQLAlchemy?'primaryjoin' 和 'secondaryjoin' 如何处理 SQLAlchemy 中的多对多关系?
【发布时间】:2013-11-05 02:05:56
【问题描述】:

在理解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.ids 添加到关联表中的?
  2. 既然primaryjoinsecondaryjoin 都有user.id 的要求,那么user.id 去哪里?
  3. 在我的关注/取消关注方法中,SQLAlchemy 如何知道自己是关注者,而传入的用户是被关注者?

这些问题一直阻碍我进入下一章,因此非常感谢任何答案。

【问题讨论】:

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


    【解决方案1】:
    1. 在多对多关系中,primaryjoin 表达式描述左表和联结表之间的联结,secondaryjoin 描述联结表和右表之间的联结。换句话说,primaryjoin 表达式是说,“查找followers 表中follower_id 为X 的所有行”,secondaryjoin 表达式是说“查找followers 表中followers_id 为X 的所有行”,然后将这两者放在一起找到关注用户 X 的所有用户,以及用户 X 关注的所有用户。

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

    3. 因为您将其添加到 self.followed 集合中,所以告诉 SQLAlchemy 有人在关注自己。如果你将它添加到 self.followers 集合中,你会做相反的事情,告诉 SQLAlchemy 'user' 是 self 的追随者。

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

    【讨论】:

    • 澄清一下,当你说“它做相反的事情”时,是不是使用secondaryjoin从另一个方向查询?
    • @PedroWerneck 你能详细说明你的 3 号吗?如果它附加在self.followers 中,为什么它会反其道而行之?为什么follower_idfollowed_id 会自动填充?self.followers 究竟是如何知道谁在关注谁?
    猜你喜欢
    • 2014-04-02
    • 2015-01-20
    • 2015-02-11
    • 2021-09-24
    • 2023-04-02
    • 2017-07-12
    • 2021-01-28
    • 2020-10-09
    • 2018-09-17
    相关资源
    最近更新 更多