SQLAlchemy DELETE Error causado por tener una carga lenta y una versión dinámica de la misma relación

Aquí hay un código de ejemplo:

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

Entonces, lo que sucede aquí es que si agrega un grupo de usuarios a un grupo como este:

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

y luego tratar de eliminar el grupo

 session.delete(g) session.commit() 

Obtendrá alguna forma de este error:

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

Eliminar la segunda versión de la relación (la dinámica en mi caso) soluciona este problema. Ni siquiera estoy seguro de por dónde empezar en términos de entender por qué está sucediendo esto. He estado utilizando 2 versiones de varias relaciones en muchos casos a lo largo de mis modelos de SQLAlchemy para facilitar el uso de la estrategia de consulta más adecuada en una situación. Esta es la primera vez que ha causado un problema inesperado.

Cualquier consejo es bienvenido.

tanto las relaciones Group.users como Group.users_dynamic intentan conciliar el hecho de que el Grupo se está eliminando junto con la posibilidad de administrar los objetos User() que hacen referencia; una relación se realiza correctamente mientras que la segunda falla, ya que las filas en la tabla de asociación ya se eliminaron. La solución más sencilla es marcar todas las relaciones, excepto una, como idénticas:

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

Si aún desea que ambas relaciones manejen cierto grado de mutaciones, deberá hacerlo con cuidado, ya que SQLAlchemy no sabe cómo coordinar los cambios en dos relaciones al mismo tiempo, por lo que los conflictos como este pueden continuar. sucede (como inserciones dobles, etc.) si haces mutaciones equivalentes en ambas relaciones. Para resolver el problema de “eliminar” por sí mismo, también puede intentar configurar Group.users_dynamic en 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') 

Acabo de añadir otra solución simple.

Puede eliminar las colecciones antes de eliminar el elemento en sí:

 >>> for user in group.users: group.users.remove(user) >>> db.session.delete(group) >>> db.session.commit() 

Alternativamente, también puedes configurarlo como una lista vacía:

 >>> group.users = [] >>> db.session.commit() >>> db.session.delete(group) >>> db.session.commit()