SQLAlchemy配置自关联的多对多关系

3 投票
1 回答
2000 浏览
提问于 2025-04-17 00:57

我在配置一个模型的多对多关系时遇到了问题。当我使用普通的关系配置时,也就是不使用关联对象的情况,我可以成功配置自我多对多关系。

在这个情况下,我需要在多对多的表中记录一些额外的信息,所以我想使用一个关联对象(PageLink)来实现这个关系。

以下是我的模型。

class PageLink(Base):
    '''
    Association table.
    '''
    __tablename__ = 'page_links'

    id = Column(Integer,primary_key=True)
    page_from = Column(Integer,ForeignKey('page.id'),primary_key=True)
    page_to = Column(Integer,ForeignKey('page.id'),primary_key=True)
    extra_col1 = Column(String(256),nullable=False)

class Page(Base):
    '''
    main table
    '''

    __tablename__ = 'page'

    id = Column(Integer,primary_key=True)
    name = Column(String(56),nullable=False)

    linked = relationship('PageLinks',backref='parent_page',
                          primaryjoin=id==PageLink.page_from,
                          secondaryjoin=id==PageLink.page_to)

但是这种方法并不奏效。我尝试去掉'secondaryjoin'这个关键词,但还是不行。

如果能得到任何帮助或建议,我将非常感激。

谢谢你的阅读。

1 个回答

5

关联对象模式并不是多对多关系的一个特例,而是一种特殊的一对多关系。在这种关系中,你会有一个 left_table(左表)与 association_table(关联表)之间的多对一关系,再加上 association_tableright_table(右表)之间的一对多关系。简单来说,你需要有两个关系,而且这两个关系都不应该有 secondarysecondaryjoin

class PageLink(Base):
    '''
    Association table.
    '''
    __tablename__ = 'page_links'

    id = Column(Integer,primary_key=True)
    page_from = Column(Integer,ForeignKey('page.id'),primary_key=True)
    page_to = Column(Integer,ForeignKey('page.id'),primary_key=True)
    extra_col1 = Column(String(256),nullable=False)

class Page(Base):
    '''
    main table
    '''

    __tablename__ = 'page'

    id = Column(Integer,primary_key=True)
    name = Column(String(56),nullable=False)

    linked_to = relationship('PageLinks',backref='parent_page',
                             primaryjoin=id==PageLink.page_from)
    linked_from = relationship('PageLinks',backref='child_page',
                               primaryjoin=id==PageLink.page_to)

这意味着,要从某个页面 p 访问额外的列,你需要这样做:p.linked_to[0].extra_col1,或者要获取实际链接的页面,你可以用 p.linked_to[0].page_to


顺便提一下,使用自增主键或者(左/右)外键对作为关联的主键通常是个不错的主意,但几乎从来不建议将两者都放在主键中。一个结合了这两种思路的替代方案是,使用一个自增整数作为主键的唯一列,并在左/右外键列上添加额外的唯一约束。

撰写回答