首页 > 解决方案 > 无法从 Django sqlite3 数据库中删除项目,出现错误“外键约束失败”

问题描述

我的 Django sqlite3 数据库中有一些不可删除或不可编辑的项目。尝试删除这些项目时,我得到integrity error: foreign key constraint failed.

令人沮丧的是,我的数据库中的大多数项目都不是这种情况。我相信它只会影响几行,我必须在对模型进行一些调整之前创建这些行。我不记得我对models.py文件做了哪些确切的更改,但我不认为这有什么大不了的。我没有关于我所做的迁移的信息,因为我删除了这些文件,认为它可能会解决问题。

我已经包含了一个models.py当前如何设置类的示例。没有什么复杂的标准模型,带有一个简单的外键,甚至不是必填字段。

我已经尝试编辑我的迁移文件,完全删除我的迁移历史,通过models.py.

models.py

class ExampleOne(models.Models):
    title = model.CharField(max_length=500, null=True, blank=True)

class ExampleTwo(models.Models):
    title = model.CharField(max_length=500, null=True, blank=True)
    example_one = models.ForeignKey(ExampleOne, null=True, blank=True, on_delete=models.CASCADE)

我宁愿不删除我的数据库文件。我希望能够删除 exampleone 和 exampletwo 的这些实例,但是当我尝试删除在调整模型文件之前创建的任何项目时,我收到错误消息:

django.db.utils.IntegrityError: FOREIGN KEY constraint failed

标签: pythondjangodjango-modelssqliteforeign-keys

解决方案


这是因为您缺少 ForeignKey 中的 on_delete,它在新的 Django 版本中是强制性的。

根据您的应用添加以下 on_delete 并进行迁移并再次迁移。那么应该没问题。

来自文档:https ://docs.djangoproject.com/en/2.2/ref/models/fields/#arguments

ForeignKey 接受定义关系如何工作的细节的其他参数。

ForeignKey.on_delete

当 ForeignKey 引用的对象被删除时,Django 将模拟 on_delete 参数指定的 SQL 约束的行为。例如,如果您有一个可为空的 ForeignKey,并且您希望在删除引用的对象时将其设置为 null:

user = models.ForeignKey(
    User,
    models.SET_NULL,
    blank=True,
    null=True,
)

on_delete 不会在数据库中创建 SQL 约束。以后可能会实现对数据库级级联选项的支持。

on_delete 的可能值在 django.db.models 中找到:

级联

级联删除。Django 模拟 SQL 约束 ON DELETE CASCADE 的行为,并删除包含 ForeignKey 的对象。

Model.delete() 不会在相关模型上调用,但会为所有已删除对象发送 pre_delete 和 post_delete 信号。

保护

通过引发 django.db.IntegrityError 的子类 ProtectedError 来防止删除引用的对象。

SET_NULL

设置外键为空;这只有在 null 为 True 时才有可能。

SET_DEFAULT 将 ForeignKey 设置为其默认值;必须设置 ForeignKey 的默认值。

放()

将 ForeignKey 设置为传递给 SET() 的值,或者如果传入了可调用对象,则为调用它的结果。在大多数情况下,需要传递一个可调用对象以避免在导入 models.py 时执行查询:

    from django.conf import settings
    from django.contrib.auth import get_user_model
    from django.db import models

    def get_sentinel_user():
        return get_user_model().objects.get_or_create(username='deleted')[0]

    class MyModel(models.Model):
        user = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.SET(get_sentinel_user),
        )

没做什么

不采取行动。如果您的数据库后端强制执行引用完整性,这将导致 IntegrityError,除非您手动将 SQL ON DELETE 约束添加到数据库字段。


推荐阅读