Я нашел много объяснений того, как создать самосвязанную связь «многие ко многим» (для последователей или друзей пользователя), используя отдельную таблицу или класс:
Ниже приведены три примера, один из которых принадлежит Майку.Сам Байер:
Но в каждом примере яобнаружено, что синтаксис для определения primaryjoin
и secondaryjoin
в отношениях является ранним обязательным:
# this relationship is used for persistence
friends = relationship("User", secondary=friendship,
primaryjoin=id==friendship.c.friend_a_id,
secondaryjoin=id==friendship.c.friend_b_id,
)
Это прекрасно работает, за исключением одного обстоятельства: когда используется класс Base
чтобы определить столбец id
для всех ваших объектов, как показано в Миксины: добавление базы из документов
Мой Base
класс и таблица followers
определены следующим образом:
from flask_sqlchalchemy import SQLAlchemy
db = SQLAlchemy()
class Base(db.Model):
__abstract__ = True
id = db.Column(db.Integer, primary_key=True)
user_flrs = db.Table(
'user_flrs',
db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
db.Column('followed_id', db.Integer, db.ForeignKey('user.id')))
Но теперь у меня есть трУдвойте отношения с последователями, которые некоторое время верноподданно служили мне, прежде чем я переместил id
в миксин:
class User(Base):
__table_name__ = 'user'
followed_users = db.relationship(
'User', secondary=user_flrs, primaryjoin=(user_flrs.c.follower_id==id),
secondaryjoin=(user_flrs.c.followed_id==id),
backref=db.backref('followers', lazy='dynamic'), lazy='dynamic')
db.class_mapper(User) # trigger class mapper configuration
Предположительно, потому что id
отсутствует в локальной области, хотякажется, для этого выдается странная ошибка:
ArgumentError: Не удалось найти какие-либо простые выражения равенства, включающие локально сопоставленные столбцы внешнего ключа для условия первичного соединения 'user_flrs.follower_id = :follower_id_1'
в отношении User.followed_users
.Убедитесь, что ссылающиеся столбцы связаны с ForeignKey
или ForeignKeyConstraint
или помечены в условии соединения аннотацией foreign()
.Чтобы разрешить операторам сравнения, отличным от '=='
, отношение может быть помечено как viewonly=True
.
И оно выдает ту же ошибку, если я заменю скобки на кавычки, чтобы воспользоваться преимуществами позднего связывания.Я понятия не имею, как аннотировать эту вещь с помощью foreign()
и remote()
, потому что я просто не знаю, что sqlalchemy хотел бы, чтобы я описал как чужеродные и удаленные в отношении самоссылки, которое пересекает вторичную таблицу!Я перепробовал множество комбинаций этого, но до сих пор это не сработало.
У меня была очень похожая (хотя и не идентичная) проблема с самоотносительными отношениями, которая не охватить отдельную таблицу, и ключом было просто преобразовать аргумент remote_side
в аргумент с поздней привязкой.Это имеет смысл для меня, поскольку столбец id
отсутствует во время процесса раннего связывания.
Если у меня возникли проблемы с поздним связыванием, пожалуйста, сообщите.Однако в текущей области я понимаю, что id
сопоставлен со встроенной в Python id()
и, следовательно, не будет работать в качестве отношения раннего связывания.
Преобразование id
в Base.id
вобъединение приводит к следующей ошибке:
ArgumentError: Не удалось найти какие-либо простые выражения равенства, включающие локально сопоставленные столбцы внешнего ключа для условия первичного соединения 'user_flrs.follower_id = "<name unknown>"'
в отношении User.followed_users
.Убедитесь, что ссылающиеся столбцы связаны с ForeignKey
или ForeignKeyConstraint
или помечены в условии соединения аннотацией foreign()
.Чтобы разрешить операторам сравнения, отличным от '=='
, отношение может быть помечено как viewonly=True
.