Уведомления

Группа в Telegram: @pythonsu

#1 Март 14, 2016 09:46:20

moskitos80
От: Luna
Зарегистрирован: 2015-01-28
Сообщения: 18
Репутация: +  0  -
Профиль  

Sqlalchemy.exc.ArgumentError: Error creating backref on relationship

Всем привет.
Столкнулся с такой проблемой. Мне надо реализовать отношение многие-ко-многим в рамках одной таблицы. Используется 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 я в курсе. Мне нужно по-возможности иметь код такой, как показан.

Офлайн

#2 Март 14, 2016 12:36:04

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Sqlalchemy.exc.ArgumentError: Error creating backref on relationship

Так пойдет?

from sqlalchemy import create_engine
from sqlalchemy.ext.automap import automap_base, name_for_collection_relationship
engine = create_engine('sqlite:////home/pooh/test.db', echo=True)
AutoBase = automap_base()
def _name_for_collection_relationship(base, local_cls, referred_cls, constraint):
    if local_cls.__name__ == 'users':
        if 'child_id' in constraint.column_keys:
            return 'child_list'
        else:
            return 'parent_list'
    else:
        return name_for_collection_relationship(base, local_cls, referred_cls, constraint)
AutoBase.prepare(engine, reflect=True,
                 name_for_collection_relationship=_name_for_collection_relationship)
u = AutoBase.classes.users(
    name='vasya',
    email='vasya'
)



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#3 Март 14, 2016 12:52:47

moskitos80
От: Luna
Зарегистрирован: 2015-01-28
Сообщения: 18
Репутация: +  0  -
Профиль  

Sqlalchemy.exc.ArgumentError: Error creating backref on relationship

PooH
PooH
Благодарю. Работает. Примерно так я и предполагал. Только вот не хватило ума на
… if ‘child_id’ in constraint.column_keys …
Мне опыт в копилку. Вам, уважаемый “+” в карму

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version