由于具有相同关系的延迟加载和动态版本而导致的 SQLAlchemy DELETE 错误 [英] SQLAlchemy DELETE Error caused by having a both lazy-load AND a dynamic version of the same relationship

查看:25
本文介绍了由于具有相同关系的延迟加载和动态版本而导致的 SQLAlchemy DELETE 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一些示例代码:

users_groups = Table('users_groups', Model.metadata,
    Column('user_id', Integer, ForeignKey('users.id')),
    Column('group_id', Integer, ForeignKey('groups.id'))
)

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


class Group(Model):
    __tablename__ = 'groups'
    id = Column(Integer, primary_key=True)

    users = relationship('User', secondary=users_groups, lazy='select', backref='groups')
    users_dynamic = relationship('User', secondary=users_groups, lazy='dynamic')

所以这里发生的情况是,如果您像这样将一群用户添加到一个组中:

So what happens here is that if you add a bunch of users to a group like so:

g = Group()
g.users = [User(), User(), User()]
session.add(g)
session.commit()

然后尝试删除该组

session.delete(g)
session.commit()

您将收到某种形式的此错误:

You will get some form of this error:

DELETE statement on table 'users_groups' expected to delete 3 row(s); Only 0 were matched.

删除关系的第二个版本(在我的情况下是动态版本)解决了这个问题.我什至不知道从哪里开始理解为什么会发生这种情况.在整个 SQLAlchemy 模型中,我在许多情况下一直使用 2 个版本的各种关系,以便在特定情况下轻松使用最合适的查询策略.这是第一次出现意外问题.

Removing the 2nd version of the relationship (the dynamic one in my case) fixes this problem. I am not even sure where to begin in terms of understanding why this is happening. I have been using 2 versions of various relationships in many cases throughout my SQLAlchemy models in order to make it easy to use the most appropriate query-strategy given a situation. This is the first time it has caused an unexpected issue.

欢迎任何建议.

推荐答案

Group.users 和 Group.users_dynamic 关系都试图调和这样一个事实,即 Group 被删除以及能够管理 User() 他们引用的对象;一个关系成功而第二个关系失败,因为关联表中的行已经被删除.最直接的解决方案是将除一个相同关系之外的所有关系标记为仅查看:

both the Group.users and Group.users_dynamic relationships are attempting to reconcile the fact that the Group is being deleted along with being able to manage the User() objects they refer to; one relationship succeeds while the second one fails, as the rows in the association table were already deleted. The most straightforward solution is to mark all but one of the identical relationships as viewonly:

class Group(Base):
    __tablename__ = 'groups'
    id = Column(Integer, primary_key=True)

    users = relationship('User', secondary=users_groups, lazy='select', backref='groups')
    users_dynamic = relationship('User', viewonly=True, secondary=users_groups, lazy='dynamic')

如果你仍然想让两个关系处理某种程度的突变,你需要小心地做这件事,因为 SQLAlchemy 不知道如何同时协调两个关系的变化,所以像这样的冲突如果您对两种关系进行等效的突变,则可能会继续发生(如双插入等).为了自己处理删除"问题,您还可以尝试将 Group.users_dynamic 设置为passive_deletes=True:

if you're still wanting to have both relationships handle some degree of mutations, you'd need to do this carefully as SQLAlchemy doesn't know how to coordinate among changes in two relationships at the same time, so conflicts like this can continue to happen (like double inserts, etc) if you make equivalent mutations on both relationships. To just take care of the "delete" issue by itself, you can also try setting Group.users_dynamic to passive_deletes=True:

class Group(Base):
    __tablename__ = 'groups'
    id = Column(Integer, primary_key=True)

    users = relationship('User', secondary=users_groups, lazy='select', backref='groups')
    users_dynamic = relationship('User', passive_deletes=True, secondary=users_groups, lazy='dynamic')

这篇关于由于具有相同关系的延迟加载和动态版本而导致的 SQLAlchemy DELETE 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆