如何在SQLAlchemy中定义两个指向同一表的关系

32 投票
4 回答
23781 浏览
提问于 2025-04-17 03:03

我在SQLAlchemy的教程和其他类似问题中查找了很多资料,但我似乎一直在努力让这个连接(join)正常工作:

场景:我有一个叫做pages的表,它用Page模型来表示。页面可以由一个用户创建,也可以由另一个用户编辑,但不一定是同一个人。我的Page模型大致是这样的(简化版):

class Page(Base):
    __tablename__ = 'pages'

    id = Column(Integer, primary_key = True)
    slug = Column(Text)
    title = Column(Text)
    direct_link = Column(Text)
    body = Column(Text)
    category_id = Column(Integer, ForeignKey('categories.id'))
    published_on = Column(DateTime)
    publishing_user_id = Column(Integer, ForeignKey('users.id'))
    last_edit_on = Column(DateTime)
    last_edit_user_id = Column(Integer, ForeignKey('users.id'))

    # Define relationships
    publish_user = relationship('User', backref = backref('pages', order_by = id), primaryjoin = "Page.publishing_user_id == User.id")
    edit_user = relationship('User', primaryjoin = "Page.last_edit_user_id == User.id")
    category = relationship('Category', backref = backref('pages', order_by = id))

我的用户信息存储在一个叫做users的表中,用User模型表示。正如我所说,我已经在SQLAlchemy的文档中查找过这个问题,尽量让它看起来和他们的例子相似,但还是没有成功。如果能得到任何帮助,我将非常感激。

4 个回答

4

试试用 foreign_keys 这个选项:

publish_user = relationship(User, foreign_keys=publishing_user_id,
                                  primaryjoin=publishing_user_id == User.id,
                                  backref=backref('pages', order_by=id))
edit_user = relationship(User, foreign_keys=last_edit_user_id,
                               primaryjoin=last_edit_user_id == User.id)
16

我觉得你差不多理解对了;不过在定义 primaryjoin 的时候,你应该用 Table 的名字,而不是 Model 的名字。所以你应该把

# Define relationships
publish_user = relationship('User', backref = backref('pages', order_by = id), 
    primaryjoin = "Page.publishing_user_id == User.id")
edit_user = relationship('User', 
    primaryjoin = "Page.last_edit_user_id == User.id")

改成:

# Define relationships
publish_user = relationship('User', backref = backref('pages', order_by = id), 
    primaryjoin = "pages.publishing_user_id == users.id")
edit_user = relationship('User', 
    primaryjoin = "pages.last_edit_user_id == users.id")
31

从0.8版本开始,SQLAlchemy可以仅通过在relationship中使用foreign_keys这个关键词参数来解决模糊的连接问题。

publish_user = relationship(User, foreign_keys=[publishing_user_id],
                                  backref=backref('pages', order_by=id))
edit_user = relationship(User, foreign_keys=[last_edit_user_id])

详细信息请查看文档:http://docs.sqlalchemy.org/en/rel_0_9/orm/join_conditions.html#handling-multiple-join-paths

撰写回答