Столкнулся с такой проблемой. Мне надо реализовать отношение многие-ко-многим в рамках одной таблицы. Используется SQLAlchemy. Есть пара таблиц:
users:
id (PK)
name
users_friendship:
parent_id (FK к users.id)
child_id (FK к users.id)
users ссылается сама на себя через таблицу-отношение users_friendship В общем данная схема определяется в коде:
... class User(Base): __tablename__ = 'users' id = Column(Integer(), primary_key=True) name = Column(String(255)) class Friendship(Base): __tablename__ = 'users_friendship' parent_id = Column(Integer(), ForeignKey('users.id'), primary_key=True) child_id = Column(Integer(), ForeignKey('users.id'), primary_key=True) Base.metadata.create_all()
Все вроде ничего, и даже работает, но вот если попробовать “отразить” схему БД в код, например в другом приложении, таким образом:
from sqlalchemy.ext.automap import automap_base ... AutoBase = automap_base() AutoBase.prepare(reflect=True) u = AutoBase.classes.users( name='vasya', email='vasya' )
То именно в строке u = AutoBase.classes.users(… - возникает ошибка:
sqlalchemy.exc.ArgumentError: Error creating backref ‘users_collection’ on relationship ‘users.users_collection’: property of that name exists on mapper ‘Mapper|users|users’
Я понимаю, что причина в том что оба поля (users_friendship.parent_id и users_friendship.child_id) имеют ключи к одному и тому же полю
и что маппер при построении backref-а сущности спотыкается при повторном создании существующего св-ва users.users_collection, но я не могу никак найти решение. Я знаю что можно задать имя формируемого св-ва если настроить маппер в этом месте:
... def name_for_collection_relationship(base, local_cls, referred_cls, constraint): return referred_cls.__name__.lower() + "_collection" # Дефолтная реализация AutoBase.prepare(reflect=True, name_for_collection_relationship=name_for_collection_relationship) ...
ЗЫ:
Про remote_side я в курсе. Мне нужно по-возможности иметь код такой, как показан.