【问题标题】:Sqlalchemy error, multiple foreign keys references to the same table and columnSqlalchemy 错误,多个外键引用同一个表和列
【发布时间】:2021-05-02 14:38:58
【问题描述】:

我已经尝试了来自this 问题和this 的解决方案,但失败了(这些解决方案都在这里),我不知道另外说什么,从逻辑上讲,FK(发件人和收件人)都必须存在在用户中,从技术上讲,这里的所有外观都是正确的

class User(Base):
    __tablename__ = "users"
    # # # META # # #
    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True, index=True, nullable=False)    
    # # # RELATIONSHIPS # # #
    messages = relationship("Message",  back_populates="users", cascade="all, delete")


class Message(Base):
    __tablename__ = "messages"

    id = Column(Integer, primary_key=True)
    sender = Column(Integer, ForeignKey('users.id'), nullable=False)
    recipient = Column(Integer, ForeignKey('users.id'), nullable=False)
    data = Column(String, nullable=False)
    created_datetime = Column(DateTime, server_default=func.now())
    # # # RELATIONSHIPS # # #
    senders = relationship("User", foreign_keys=[sender], back_populates="messages")
    recipients = relationship("User", foreign_keys=[recipient], back_populates="messages")


sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship User.messages - there are multiple foreign key paths linking the tables.  Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table.
python-BaseException

我尝试了什么:

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True, index=True, nullable=False)
    sent_messages = relationship("Message",  back_populates="users", cascade="all, delete")
    received_messages = relationship("Message",  back_populates="users", cascade="all, delete")


class Message(Base):
    __tablename__ = "messages"

    id = Column(Integer, primary_key=True)
    sender = Column(Integer, ForeignKey('users.id'), nullable=False)
    recipient = Column(Integer, ForeignKey('users.id'), nullable=False)
    data = Column(String, nullable=False)
    created_datetime = Column(DateTime, server_default=func.now())
    senders = relationship("User", foreign_keys=[sender], back_populates="messages")
    recipients = relationship("User", foreign_keys=[recipient], back_populates="messages")

Could not determine join condition between parent/child tables on relationship User.sent_messages - there are multiple foreign key paths linking the tables.  Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table.

【问题讨论】:

  • 在 Users 类中,尝试为 sent_messagesreceived_messages 创建单独的关系,而不是将它们全部放在一个关系中。
  • @GordThompson 查看更新的答案

标签: python sqlalchemy flask-sqlalchemy


【解决方案1】:

这在 1.4 版中适用于我:

class Message(Base):
    __tablename__ = "messages"
    id = sa.Column(sa.Integer, primary_key=True)
    sender_id = sa.Column(
        sa.String(10), sa.ForeignKey("users.id"), nullable=False
    )
    recipient_id = sa.Column(
        sa.String(10), sa.ForeignKey("users.id"), nullable=False
    )
    data = sa.Column(sa.String, nullable=False)
    sender = relationship(
        "User", foreign_keys=[sender_id], back_populates="sent_messages"
    )
    recipient = relationship(
        "User", foreign_keys=[recipient_id], back_populates="received_messages"
    )

    def __repr__(self):
        return f"<Message(id={self.id}, data='{self.data}')>"


class User(Base):
    __tablename__ = "users"
    id = sa.Column(sa.String(10), primary_key=True)
    sent_messages = relationship(
        "Message",
        foreign_keys=[Message.sender_id],
        back_populates="sender",
        cascade="all, delete",
    )
    received_messages = relationship(
        "Message",
        foreign_keys=[Message.recipient_id],
        back_populates="recipient",
        cascade="all, delete",
    )

    def __repr__(self):
        return f"<User(id='{self.id}')>"


Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)

with sa.orm.Session(engine, future=True) as session:
    gord = User(id="gord")
    david = User(id="david")
    msg = Message(sender=gord, recipient=david, data="Hello, David!")
    session.add(msg)  # dependent objects are added automatically
    session.commit()

    results = session.execute(sa.text("SELECT * FROM messages")).fetchall()
    print(results)
    # [(1, 'gord', 'david', 'Hello, David!')]

    print(david.received_messages)
    # [<Message(id=1, data='Hello, David!')>]

【讨论】:

    猜你喜欢
    • 2021-07-02
    • 1970-01-01
    • 2013-06-03
    • 2016-12-23
    • 1970-01-01
    • 2017-11-10
    • 1970-01-01
    • 2019-11-24
    • 2015-02-04
    相关资源
    最近更新 更多