【问题标题】:SQLAlchemy many to many dynamic lazyload not returning AppenderQuerySQLAlchemy 多对多动态延迟加载不返回 AppenderQuery
【发布时间】:2020-11-27 14:40:48
【问题描述】:

我正在尝试掌握 SQLAlchemy ORM 的 backref 延迟加载动态特性。

我有 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'

当我尝试使用成员时,结果相同。

使用成员和课程作为工作的列表对象:

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

但我真的很怀念 AppenderQuery 类的功能,用于我的课程查询。

这是正常行为还是我错过了什么?

【问题讨论】:

    标签: python orm sqlalchemy flask-sqlalchemy relationship


    【解决方案1】:

    在写问题和研究时,我在add dynamic to the other side这个帖子中找到了问题的答案。

    在看到答案后,我对关系功能也有了更多了解。

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

    成员和角色关系是父类的功能,backref=*是子类的关系功能。我花了比我想意识到这一点更多的时间。但是通过在关系函数中使用lazy='dynamic' 作为参数,并且 backref 参数的 backref 函数有效地将其应用于关系的双方。

    现在用户、课程和角色作为 AppenderQuery 返回。

    希望这将有助于其他人寻找问题。

    【讨论】:

    • 我去找了一个我可以回答的问题以获得足够的声誉来发表评论:谢谢!我遇到了这个确切的问题。您应该将此标记为已接受的答案(即使您自己回答了)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多