【问题标题】:Sqlalchemy Multiple Foreign Keys in secondary table辅助表中的 Sqlalchemy 多个外键
【发布时间】:2020-08-16 10:33:08
【问题描述】:

我从这个设置开始:

checklist_participants = Table('checklist_participants', base.metadata,
                               Column('checklist_id', Integer, ForeignKey('checklists.id', ondelete='cascade')),
                               Column('user_id', Integer, ForeignKey('users.id', ondelete='cascade'))
                               )

class Checklist(base):
    __tablename__ = 'checklists'

    id = Column(Integer, primary_key=True)
    participants = relationship('User', secondary='checklist_participants', back_populates='joined_checklists')

class User(base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    joined_checklists = relationship('Checklist', secondary='checklist_participants', back_populates='participants')

为了给辅助表checklist_participants 提供一个额外的列referring_user,我将它移到了自己的类中,如下所示:

# new class
class Participant(base):
    checklist_id = Column(Integer, ForeignKey('checklists.id', ondelete='cascade'), primary_key=True)
    checklist = relationship('Checklist', foreign_keys=checklist_id)
    user_id = Column(Integer, ForeignKey('users.id', ondelete='cascade'), primary_key=True)
    user = relationship('User', foreign_keys=user_id)
    # new column
    referring_user_id = Column(Integer, ForeignKey('users.id', ondelete='set null'))
    referring_user = relationship('User', foreign_keys=referring_user_id)

class User(base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    joined_checklists = relationship('Checklist', secondary='checklist_participants', back_populates='participants')
    # new relationship definition
    referred_participants = relationship('Participant', back_populates='referring_user')

简单地将连接表移动到它自己的类中不会导致任何问题。但是当我介绍新列并尝试运行一个简单的查询时:
session.query(User).filter(User.id == input_id).scalar()
我收到了这个错误:
sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship Checklist.participants - there are multiple foreign key paths linking the tables via secondary table 'checklist_participants'. Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference from the secondary table to each of the parent and child tables.

我需要在我的模型上定义什么来解决这个问题?

【问题讨论】:

  • 请在采用关联对象模式后在UserParticipant中包含您的关系定义。长话短说,您需要明确说明UserParticipant 之间的关系要使用哪些外键列,如下所示:stackoverflow.com/questions/22355890/…。在您显示的查询中,您没有连接,因此错误似乎是由关系引起的。
  • @IljaEverilä 我添加了关系定义,但遇到了关于 foreign_keys 参数的新错误。我编辑了主要帖子以显示我的更改和新错误。我不明白为什么这个错误与Checklist.participants 有关...我的Participant 表只有一个指向Checklist 的外键,所以选择的键应该没有混淆。
  • 如果Checklist.participants 仍然是User 的关系,那么在添加第二个外键后,从清单到用户有多个路径。
  • 我明白了。所以我必须告诉Checklist.participants 关系必须使用辅助表上的哪个foreign_key 来连接到User?如果我尝试将foreign_keys='Participant.user_id' 添加到Checklist.participants 关系中,我会得到另一个新异常:`sqlalchemy.exc.NoForeignKeysError:无法确定关系 Checklist.participants 上父/子表之间的连接条件 - 没有外键链接这些表通过辅助表“checklist_participants”。

标签: python postgresql flask sqlalchemy


【解决方案1】:

在@IljaEverilä 的帮助下,我意识到为什么这些关系是模棱两可的。我不知道如何告诉Checklist.participants 连接表上的哪个外键是要使用的。相反,我从我的关系中删除了secondary 参数,并使ChecklistUser 关系连接到Participant,而不是直接相互引用。这样,Checklist 就不需要知道Participant 中使用的外键。
但是,这些更改将问题转移到了User 类,我现在在该类中引用了Participant 两次。这一次,我能够在这两个 ManyToOne 关系上定义 foreign_keys 参数来解决歧义:

class User(base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    participants = relationship('Participant', back_populates='user', foreign_keys='Participant.user_id')
    referred_participants = relationship('Participant', back_populates='referring_user', foreign_keys='Participant.referring_user_id')


class Checklist(base):
    __tablename__ = 'checklists'

    id = Column(Integer, primary_key=True)
    participants = relationship('Participant', back_populates='checklist')

class Participant(base):
    __tablename__ = 'checklist_participants'

    checklist_id = Column(Integer, ForeignKey('checklists.id', ondelete='cascade'), primary_key=True)
    checklist = relationship('Checklist', foreign_keys=checklist_id)
    user_id = Column(Integer, ForeignKey('users.id', ondelete='cascade'), primary_key=True)
    user = relationship('User', foreign_keys=user_id)
    referring_user_id = Column(Integer, ForeignKey('users.id', ondelete='set null'))
    referring_user = relationship('User', foreign_keys=referring_user_id)

【讨论】:

  • 很好,但这不是问题的答案,因为现在在辅助表错误中有多个外键的人被重定向到这里,您建议删除辅助表
  • 同意,仍然 - 让我看,你的评论,@Superpassteque,给了我进一步看的提示,我想我在这里找到了一些关于这个主题的内容:realpython.com/python-sqlite-sqlalchemy - 确实 - 阅读该页面复制这个概念让我的警告消失了。
猜你喜欢
  • 1970-01-01
  • 2015-08-01
  • 2019-11-24
  • 2012-04-12
  • 2021-06-15
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多