python - sqlachemy 多对多:删除不起作用,删除太多
问题描述
我正在做一个项目,包括链接两个类:用户和组。
一个用户可以在一些组中,每个组可以有一些用户。
因此,我创建了第三个表:group_guest,用于保存 user_id 和 group_id。
当我创建 user1、user2、group1 和 group2 时,我可以将 group1 和 group2 添加到 user1。
并将 group1 添加到 user2
问题:那么我不能只从 user1 中删除 group1 并且删除 group1 不好:user2 没有更多组:/
我已经尝试了几乎所有的组合:级联,反向引用,删除孤儿......
如果有人作为一个想法......我应该修改模型吗?
我将不胜感激!
代码:
from app import db
from flask_login import UserMixin
group_guest = db.Table('group_guest',
db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
db.Column('group_id', db.Integer, db.ForeignKey('group.id'))
)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
group_guest_group_id = db.relationship(
"Group",
secondary=group_guest,
back_populates="group_guest_user_id",
cascade="all, delete",
lazy='dynamic'
)
class Group(db.Model):
id = db.Column(db.Integer, primary_key=True)
entitled = db.Column(db.String(64))
group_guest_user_id = db.relationship(
"User",
secondary=group_guest,
back_populates="group_guest_group_id",
lazy='dynamic'
)
然后 :
user1.group_guest_group_id.remove(group1)
db.session.commit()
user1.guested_group().all()
它应该(在我看来)只返回 group2 但它返回两者
解决方案
您似乎希望在整个表中建立不对称关系:
- 如果您删除 a
User
那么显然所有对它的user-group
辅助引用也User
应该被删除,即级联在辅助表中。 Group
但是如果组中至少存在一个,您不希望能够删除一个User
,删除一个活动Group
会引发完整性错误。
在这种情况下,您可以尝试以下操作:
group_guest = db.Table('group_guest',
db.Column('user_id', db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), primary_key=True),
db.Column('group_id', db.Integer, db.ForeignKey('group.id', ondelete='RESTRICT'), primary_key=True)
)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
group_guest_group_id = db.relationship("Group",
secondary=group_guest,
back_populates="group_guest_user_id",
passive_deletes='all', lazy='dynamic'
)
class Group(db.Model):
id = db.Column(db.Integer, primary_key=True)
entitled = db.Column(db.String(64))
group_guest_user_id = db.relationship("User",
secondary=group_guest,
back_populates="group_guest_group_id",
passive_deletes='all', lazy='dynamic'
)
被动删除可防止 SQLAlchemy 自动执行级联删除,并且由 foreignKey 的“ondelete”指定的数据库低级指令直接指示操作。
由于辅助表上的主键不能为 NULL,因此Group
无论如何您都不能删除父表。我只是喜欢这ondelete='Restrict'
条线,因为它明确地说明了规则,并且如果您以后重新访问它,以后可以更容易地维护/调试。
已编辑
以下对我有用,没有问题:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
import uuid
Base= declarative_base()
group_guest= Table('group_guest', Base.metadata,
Column('user_id', Integer, ForeignKey('user.id', ondelete='CASCADE'), primary_key=True),
Column('group_id', Integer, ForeignKey('group.id', ondelete='RESTRICT'), primary_key=True))
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
username = Column(String(64), index=True, unique=True)
group_guest_group_id = relationship("Group",
secondary=group_guest,
back_populates="group_guest_user_id",
passive_deletes='all', lazy='dynamic'
)
class Group(Base):
__tablename__ = 'group'
id = Column(Integer, primary_key=True)
entitled = Column(String(64))
group_guest_user_id = relationship("User",
secondary=group_guest,
back_populates="group_guest_group_id",
passive_deletes='all', lazy='dynamic'
)
e = create_engine("sqlite://")
Base.metadata.create_all(e)
s = Session(e)
u1 = User(username='A')
u2 = User(username='B')
g1 = Group()
g2 = Group()
s.add_all([u1, u2, g1, g2])
s.commit()
u1.group_guest_group_id.append(g1)
u1.group_guest_group_id.append(g2)
g1.group_guest_user_id.append(u2)
g2.group_guest_user_id.append(u2)
s.add_all([u1, u2, g1, g2])
s.commit()
u1.group_guest_group_id.remove(g1)
s.add(u1)
s.commit()
print([group for group in u1.group_guest_group_id])
print([group for group in u2.group_guest_group_id])
推荐阅读
- python - Python 装饰器日志文件未生成
- java - 如何使用远程存储库中父 pom 的快照版本
- javascript - 在Javascript中逐行评估日志文件
- pytest - 误解了,来自文档Pytest授权的一个例子
- java - 如何在 Java 中编写“不等于”字符串操作
- node.js - 如何使用带有 https 的 socket.io
- android - 使用风味在 AppGallery 和 Google Play 上发布应用
- python - 使用自定义开始/结束日期显示多年的数据 - datetime, matplotlib
- big-o - 我的代码在大 O 表示法中的复杂性是多少
- python - QIcon 的 PyQt5 “Ghost”出现在 QComboBox 的 QLineEdit 中