【问题标题】:SQLAlchemy lazy=dynamic with m2m relationship using association object patternSQLAlchemy惰性=动态与m2m关系使用关联对象模式
【发布时间】:2015-03-30 21:15:33
【问题描述】:

usersroles 表之间有一个简单的 m2m 关系:

users_roles = db.Table('users_roles',
    db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
    db.Column('role_id', db.Integer, db.ForeignKey('roles.id')),
    db.Column('is_primary', db.Boolean)
)

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column('id', db.Integer, primary_key=True)
    roles = db.relationship('Role', secondary=users_roles, lazy='dynamic', backref=db.backref('users', lazy='dynamic'))

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column('id', db.Integer, primary_key=True)
    users = db.relationship('User', secondary=users_roles, lazy='dynamic', backref=db.backref('roles', lazy='dynamic'))

要将记录添加到users_roles 表中,我必须执行以下操作:

role = Role.get(1)
user = User()
user.roles.append(role)
db.session.add(user)
db.session.commit()

没关系,但我在 users_roles 表中有一个名为 is_primary 的列,也应该被填充。

我将代码更改为使用 SQLAlchemy 文档中描述的 Association Object Pattern

现在我的代码如下所示:

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column('id', db.Integer, primary_key=True)

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column('id', db.Integer, primary_key=True)

class UserRole(db.Model):
    __tablename__ = 'users_roles'
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'), primary_key=True)
    is_primary = db.Column(db.Boolean)

    user = db.relationship(User, backref="users_roles")
    role = db.relationship(Role, backref="users_roles")

User.roles = association_proxy("users_roles", "role")
Role.users = association_proxy("users_roles", "user")

效果很好,但我仍然有问题。 User.roles(与关联代理一起添加)是否有可能返回一个 AppenderBaseQuery 我可以添加更多过滤器,例如User.query.get(1).roles.filter_by(...)? 我习惯于在关系声明中使用 lazy=dynamic 来处理简单的多对多关系,但是在将类映射到关联表之后,我似乎不能再这样做了。 有没有办法做到这一点?

@IfLoop 我在此post 中遵循了您的建议。非常感谢您的帮助。

【问题讨论】:

    标签: python flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

    好吧,我最终使用以下代码过滤了roles

    roles = Role.query.filter_by(...).join(UserRole).join(User).filter_by(id=1)
    

    我仍然希望能够做这样的事情:

    roles = User.query.get(1).roles.filter_by(...).all()
    

    无论如何,如果我在几天内没有得到答案,我会接受这个作为答案。

    【讨论】:

      【解决方案2】:

      帮助您为时已晚,但我问了自己同样的问题,文档的这一段阐明了代理协会可以做什么: https://docs.sqlalchemy.org/en/14/orm/extensions/associationproxy.html#querying-with-association-proxies

      根据我的理解总结:这不是明确可能的,但是对于直接目标是相关对象或集合的关联代理,可以使用面向关系的运算符,例如 .has() 和 .any()

      我不确定这是否会对我有所帮助,但如果它可以为某人指出他们的解决方案,我将把它放在那里

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-24
        • 1970-01-01
        • 2015-03-16
        • 1970-01-01
        • 2021-05-31
        • 2020-08-06
        • 1970-01-01
        相关资源
        最近更新 更多