sqlalchemy一对多关系,其中相同的外键在模型中使用两次

spe*_*eer 1 python sqlalchemy

我有一个像这样的简单模型

class ChatMessage(Base):
    __tablename__ = 'chat_messages'
   id = Column(Integer, ForeignKey('messages.id'))
   sender_id = Column(Integer, ForeignKey('users.id'))
   receiver_id = Column(Integer, ForeignKey('users.id'))
Run Code Online (Sandbox Code Playgroud)

我尝试向用户添加消息关系.

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String, nullable=False)
    chat_messages = relationship("ChatMessage", backref="participants",
                             foreign_keys="[ChatMessage.sender_id, ChatMessage.receiver_id]")
Run Code Online (Sandbox Code Playgroud)

它给:

InvalidRequestError:一个或多个映射器无法初始化 - 无法继续初始化其他映射器.原始异常是:无法确定关系User.chat_messages上的父/子表之间的连接条件 - 有多个链接表的外键路径.指定'foreign_keys'参数,提供应列为包含对父表的外键引用的列的列表.

dav*_*ism 6

在创建两个类之后设置特殊关系.

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref

engine = sa.create_engine('sqlite:///test.db', echo=True)
Session = sessionmaker(bind=engine)
Base = declarative_base(bind=engine)


class User(Base):
    __tablename__ = 'users'
    id = sa.Column(sa.Integer, primary_key=True)


class ChatMessage(Base):
    __tablename__ = 'chat_messages'
    id = sa.Column(sa.Integer, primary_key=True)
    sender_id = sa.Column(sa.Integer, sa.ForeignKey(User.id))
    receiver_id = sa.Column(sa.Integer, sa.ForeignKey(User.id))
    content = sa.Column(sa.String, nullable=False)

    __table_args__ = (
        sa.CheckConstraint(receiver_id != sender_id),
    )

    sender = relationship(User, foreign_keys=sender_id, backref='sent_chat_messages')
    receiver = relationship(User, foreign_keys=receiver_id, backref='received_chat_messages')


User.chat_messages = relationship(ChatMessage, primaryjoin=sa.or_(
    User.id == ChatMessage.sender_id,
    User.id == ChatMessage.receiver_id
), backref=backref('participants', uselist=True, viewonly=True), viewonly=True)
Run Code Online (Sandbox Code Playgroud)

viewonly=True之所以使用,是因为此关系使用自定义连接,而SQLAlchemy不知道数据更改后该怎么做.例如,如果您追加参与者,是否会将用户添加为发件人或收件人?