gpt4 book ai didi

python - 如果父行的子行将在 SQLAlchemy 中被孤立,则防止删除父行

转载 作者:太空狗 更新时间:2023-10-29 20:53:21 26 4
gpt4 key购买 nike

我目前正在通过 flask-sqlalchemy 使用 sqlalchemy 构建数据模型

数据库在 Postgresql 服务器上

从具有关系的表中删除行时遇到问题。在这种情况下,我有多种治疗类型和一种治疗。该治疗分配了单一治疗类型。

只要我有一个或多个分配了特定治疗类型的治疗,我希望治疗类型不能被删除。就像现在一样,当我尝试时它被删除了。

我有以下模型:

class treatment(db.Model):
__tablename__ = 'treatment'
__table_args__ = (db.UniqueConstraint('title', 'tenant_uuid'),)

id = db.Column(db.Integer, primary_key=True)
uuid = db.Column(db.String(), nullable=False, unique=True)
title = db.Column(db.String(), nullable=False)
tenant_uuid = db.Column(db.String(), nullable=False)

treatmentType_id = db.Column(db.Integer, db.ForeignKey('treatmentType.id'))
riskResponse_id = db.Column(db.Integer, db.ForeignKey('riskResponse.id'))

class treatmentType(db.Model):
__tablename__ = 'treatmentType'
__table_args__ = (db.UniqueConstraint('title', 'tenant_uuid'),)

id = db.Column(db.Integer, primary_key=True)
uuid = db.Column(db.String(), nullable=False, unique=True)
title = db.Column(db.String(), nullable=False)
tenant_uuid = db.Column(db.String(), nullable=False)

treatments = db.relationship('treatment', backref='treatmentType', lazy='dynamic')

我可以在我的“删除” View 中构建一些逻辑来检查分配的处理,然后再删除处理类型,但在我看来这应该是关系数据库的标准功能。所以换句话说,我一定是做错了什么。

我像这样删除治疗类型:

entry = treatmentType.query.filter_by(tenant_uuid=session['tenant_uuid']).all()
try:
db.session.delete(entry)
db.session.commit()
return {'success': 'Treatment Type deleted'}
except Exception as E:
return {'error': unicode(E)}

正如我所说,我可以在删除处理类型之前进行检查,但如果在删除之前存在关系问题,我宁愿让 sqlalchemy 抛出错误。

最佳答案

删除 TreatmentType(父级)时,by default , SQLAlchemy 将通过设置 Treatment.treatmentType_id = None 来更新 child 。正如您所说,您只剩下一个没有 TreatmentTypeTreatment。子记录现在是“孤儿”。

有两种方法可以防止在 SQLAlchemy 中创建孤立记录。

<强>1。在子列上使用非 NULL 约束

当删除 TreatmentType(parent)时,默认情况下,SQLAlchemy 会将 Treatment.treatmentType_id(child)设置为 None(或 null在 SQL 中)当您执行此操作时,正如您所说,您将得到一个没有 TreatmentTypeTreatment

对此的解决方案是将 treatmentType_id 列更新为不可空,这意味着它必须具有非空值。我们使用 nullable=False 关键字来做到这一点:

treatmentType_id = db.Column(db.Integer, db.ForeignKey('treatmentType.id'), nullable=False)

现在,当执行默认的级联逻辑时,SQLAlchemy 会尝试设置 Treatment.treatmentType_id = NoneIntegrityError由于违反了非空约束而引发。

<强>2。使用 passive_deletes='all'

treatments = db.relationship('treatment', backref='treatmentType', passive_deletes='all')

TreatmentType 被删除时,treatments 关系上的 passive_deletes='all' 关键字“will disable the “nulling out” of the child foreign keys”。它基本上禁用了上面第一段中概述的默认行为。因此,当 ORM 尝试删除 TreatmentType 而不 首先设置 child 的 Treatment.treatmentType_id = None 时,数据库将抛出 IntegrityError。提示 child 的 ForeignKey 引用了一个不存在的 parent !

*注意:底层数据库必须支持外键才能使用此选项

关于python - 如果父行的子行将在 SQLAlchemy 中被孤立,则防止删除父行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42978090/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com