我正在研究一个项目,其中包括链接两个类:User和Group。
一个用户可以属于某些组,每个组可以具有一些用户。
因此,我创建了第三个表:group_guest,用于保存user_id和group_id。
创建用户1,用户2,组1和组2时,可以将用户1和组2添加到用户1。
并将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,但同时返回两者
答案 0 :(得分:2)
您似乎希望在整个表之间建立不对称关系:
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])