SQLAlchemy многие ко многим динамический c lazyload не возвращает AppenderQuery - PullRequest
0 голосов
/ 07 августа 2020

Я пытаюсь получить доступ к функции backref lazyload Dynami c SQLAlchemy ORM.

У меня есть 3 таблицы и две таблицы ссылок.

course_members = Table('course_members', Base.metadata,
            Column('user_id', Integer, ForeignKey('users.id')),
            Column('course_id', Integer, ForeignKey('courses.id'))
            )

course_roles = Table('course_roles', Base.metadata,
              Column('role_id', Integer, ForeignKey('roles.id')),
              Column('course_id', Integer, ForeignKey('courses.id'))
              )

class User(Base):
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(200), nullable=False)

class Course(Base, Jsonify):
    id = Column(Integer, primary_key=True, autoincrement=True)
    members = relationship('User', secondary=course_members, backref=backref('courses', lazy='dynamic'))
    roles = relationship('Role', secondary=course_roles, backref=backref('roles', lazy='dynamic'))

class Role(Base):

    id = Column(Integer, primary_key=True, autoincrement=True)
    role_id = Column(Integer, nullable=False)
    user_id = Column(Integer, ForeignKey('users.id'))
    user = relationship('User', backref=backref("roles", lazy='dynamic'))
    
    UniqueConstraint('role_id', 'user_id', name='role_combination')

С запрос пользователя:

print(type(user.roles))
print(user.roles.filter_by(id=1).first())
# print(user.courses.first() <-- Works fine too.

<class 'sqlalchemy.orm.dynamic.AppenderQuery'>
{id: 1, 'user_id': 1, role_id: 3}

Но с запросом курса:

print(type(course.roles))
print(course.roles.filter_by(id=1).first())

<class 'sqlalchemy.orm.collections.InstrumentedList'>
AttributeError: 'InstrumentedList' object has no attribute 'filter_by'

Тот же результат, когда я пытаюсь с участниками.

Использование участников и курсов как объектов списка c работа:

course.roles[0].user.first()

Но мне очень не хватает функций класса AppenderQuery для моего запроса курса.

Это нормальное поведение или я чего-то упускаю?

1 Ответ

0 голосов
/ 07 августа 2020

При написании вопроса и исследовании я нашел ответ на проблему в этом посте добавьте динамику c на другую сторону .

И, увидев ответ, я понял больше функциональность отношений также.

members = relationship('User', secondary=course_members, lazy='dynamic', backref=backref('courses', lazy='dynamic'))
roles = relationship('Role', secondary=course_roles, lazy='dynamic', backref=backref('roles', lazy='dynamic'))

Отношения членов и ролей имеют c функциональность родительского класса, а backref = * - c функциональность отношений дочернего класса. Мне потребовалось больше времени, чем мне хотелось бы, чтобы осознать это. Но наличие lazy = 'Dynami c' в качестве параметра как в функции отношения, так и в функции обратной ссылки для параметра обратной ссылки эффективно применяет это к обеим сторонам отношения.

А теперь пользователи, курсы и роли возвращаются как AppenderQuery.

Надеюсь, это поможет другим в поиске вопроса.

...