Sqlalchemy Несколько внешних ключей в дополнительной таблице - PullRequest
0 голосов
/ 02 мая 2020

Я начал с этой настройки:

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')

Чтобы добавить дополнительный столбец referring_user к дополнительной таблице checklist_participants, я переместил его в его собственный класс, например:

# 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.

Что мне нужно определить в моих моделях чтобы исправить эту проблему?

1 Ответ

1 голос
/ 02 мая 2020

С помощью @ IljaEverilä я понял, почему отношения были неоднозначными. Я не мог понять, как сказать Checklist.participants, какой внешний ключ в таблице соединений использовался. Вместо этого я удалил аргумент secondary из своих отношений и установил связь Checklist и User с Participant вместо прямой ссылки друг на друга. Таким образом, Checklist не нужно было знать о внешних ключах, используемых в Participant.
Однако эти изменения перенесли проблему в класс User, где я теперь дважды ссылался на Participant. На этот раз я смог определить аргумент foreign_keys для этих двух отношений ManyToOne, чтобы исправить неоднозначность:

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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...