[英](pymysql.err.IntegrityError) (1451, 'Cannot delete or update a parent row: a foreign key constraint fails…') in Flask
I'm aware that there are many questions about the error in the title, but I could't find a suitable solution. 我知道标题中的错误有很多问题,但是我找不到合适的解决方案。 My problem is that while deleting a row using
Session.delete()
it's throwing 我的问题是,使用
Session.delete()
删除行时,它会抛出
sqlalchemy.exc.IntegrityError: (pymysql.err.IntegrityError) (1451, 'Cannot delete or update a parent row: a foreign key constraint fails (`transport`.`driver`, CONSTRAINT `driver_ibfk_1` FOREIGN KEY (`owner_id`) REFERENCES `truckcompany` (`id`))') [SQL: 'DELETE FROM truckcompany WHERE truckcompany.id = %(id)s'] [parameters: {'id': 4}]
Models: 楷模:
class Truck_company(Base):
__tablename__ = 'truckcompany'
id = Column(BigInteger, primary_key=True)
class Driver(Base):
__tablename__ = 'driver'
id = Column(BigInteger, primary_key=True)
owner_id = Column(BigInteger, ForeignKey('truckcompany.id'))
owner = relationship(Truck_company)
The view with the failing delete: 删除失败的视图:
@app.route('/values/deleteuser/<int:id>', methods=['POST', 'GET'])
def delete_truck(id):
value_truckcompany = sqlsession.query(Truck_company).filter(Truck_company.id == id).first()
if value_truckcompany:
sqlsession.delete(value_truckcompany)
sqlsession.commit()
return redirect('/static/truckcompanyview', )
In your Driver
model there's a foreign key constraint referencing Truck_company
: 在您的
Driver
模型中,有一个外键约束引用Truck_company
:
class Driver(Base):
...
owner_id = Column(BigInteger, ForeignKey('truckcompany.id'))
You've omitted the ON DELETE action, so MySQL defaults to RESTRICT . 您已经省略了ON DELETE操作,因此MySQL 默认为RESTRICT 。 Also there are no SQLAlchemy ORM relationships with cascades that would delete the related drivers.
此外,不存在带有级联的SQLAlchemy ORM关系,该关系会删除相关的驱动程序。 So when you try to delete the truck company in the view, the DB stops you from doing that, because you'd violate your foreign key constraint and in other words referential integrity .
因此,当您尝试在视图中删除卡车公司时,数据库会阻止您这样做,因为您违反了外键约束,即违反了参照完整性 。 This is an issue with how you've modeled your DB, not Flask etc.
这是如何建模数据库而不是Flask等的问题。
The most important thing to do – when you're creating your model – is to decide what would you like to happen when you delete a truck company with related drivers. 创建模型时,最重要的事情是确定删除带有相关驾驶员的卡车公司时要发生的情况。 Your options include, but are not limited to:
您的选择包括但不限于:
owner_id
to NULL, effectively detaching them. owner_id
设置为NULL,可以有效地分离它们。 This is what SQLAlchemy does, if an ORM relationship is present in its default configuration in the parent. It is also a perfectly valid solution to restrict deleting parent rows with children, as you've implicitly done. 就像您已隐式完成的一样,这也是限制删除带有子项的父行的完美有效解决方案。
You've expressed in the comments that you'd like to remove the related drivers. 您已在评论中表示要删除相关的驱动程序。 A quick solution is to just manually issue a DELETE:
一种快速的解决方案是仅手动发出DELETE:
# WARNING: Allowing GET in a data modifying view is a terrible idea.
# Prepare yourself for when Googlebot, some other spider, or an overly
# eager browser nukes your DB.
@app.route('/values/deleteuser/<int:id>', methods=['POST', 'GET'])
def delete_truck(id):
value_truckcompany = sqlsession.query(Truck_company).get(id)
if value_truckcompany:
sqlsession.query(Driver).\
filter_by(owner=value_truckcompany).\
delete(synchronize_session=False)
sqlsession.delete(value_truckcompany)
sqlsession.commit()
return redirect('/static/truckcompanyview', )
This on the other hand fixes this one location only. 另一方面,这仅修复该位置。 If you decide that a
Driver
has no meaning without its Truck_company
, you could alter the foreign key constraint to include ON DELETE CASCADE, and use passive deletes in related SQLAlchemy ORM relationships: 如果您确定一个没有它的
Truck_company
的Driver
没有任何意义,则可以更改外键约束以包括ON DELETE CASCADE,并在相关的SQLAlchemy ORM关系中使用被动删除 :
class Truck_company(Base):
...
# Remember to use passive deletes with ON DELETE CASCADE
drivers = relationship('Driver', passive_deletes=True)
class Driver(Base):
...
# Let the DB handle deleting related rows
owner_id = Column(BigInteger, ForeignKey('truckcompany.id',
ondelete='CASCADE'))
Alternatively you could leave it to the SQLAlchemy ORM level cascades to remove related objects, but it seems you've had some problems with that in the past. 或者,您可以将其留给SQLAlchemy ORM级别级联以删除相关的对象,但是过去您似乎在此方面遇到了一些问题。 Note that the SQLAlchemy cascades define how an operation on the parent should propagate to its children, so you define
delete
and optionally delete-orphan
on the parent side relationship, or the one-to-many side: 请注意, SQLAlchemy级联定义了对父级的操作应如何传播到其子级,因此您可以在父级关系或一对多关系上定义
delete
和delete-orphan
可选):
class Truck_company(Base):
...
# If a truck company is deleted, delete the related drivers as well
drivers = relationship('Driver', cascade='save-update, merge, delete')
In your current model you have no relationship defined from Truck_company
to Driver
, so no cascades take place. 在当前模型中,从
Truck_company
到Driver
没有定义关系,因此不会发生级联。
Note that modifying Driver
such as: 请注意,修改
Driver
例如:
class Driver(Base):
...
owner_id = Column(BigInteger, ForeignKey('truckcompany.id',
ondelete='CASCADE'))
will not magically migrate the existing DB table and its constraints. 不会神奇地迁移现有的数据库表及其约束。 If you wish to take that route, you'll have to either migrate manually or using some tool.
如果您希望采用这种方式,则必须手动迁移或使用某些工具进行迁移 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.