Django 2.0: sqlite IntegrityError: FOREIGN KEY constraint failed

Django 2.0: sqlite IntegrityError: FOREIGN KEY constraint failed

我正在努力为 django-pagetree 库添加 Django 2.0 支持。在自动化测试期间,使用 sqlite 内存数据库,我收到了一堆这样的错误:

  File "/home/nnyby/src/django-pagetree/pagetree/tests/test_models.py", line 638, in setUp
    'children': [],
  File "/home/nnyby/src/django-pagetree/pagetree/models.py", line 586, in add_child_section_from_dict

...

  File "/home/nnyby/src/django-pagetree/venv/lib/python3.5/site-packages/django/db/backends/base/base.py", line 239, in _commit
    return self.connection.commit()
django.db.utils.IntegrityError: FOREIGN KEY constraint failed

Django 2.0 发行说明中对此进行了说明:https://docs.djangoproject.com/en/2.0/releases/2.0/#foreign-key-constraints-are-now-enabled-on-sqlite

从那个我不完全理解的描述来看,这不应该适用于非持久性的测试数据库,对吧?使用 Django 2.0 时,我的 sqlite 测试数据库不会使用适当的选项创建吗?

我用于测试的应用设置在这里:https://github.com/ccnmtl/django-pagetree/blob/master/runtests.py

你有添加 on_delete 到你的 FOREIGN KEY 吗?在 Django 2.0 上,此参数是必需的。 您还可以看到: https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey.on_delete https://docs.djangoproject.com/en/2.0/howto/upgrade-version/ https://docs.djangoproject.com/en/2.0/topics/db/examples/many_to_one/ https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey

文档说明了两件事:

  1. 如果您有 ForeignKey 约束,它们现在会在数据库级别强制执行。因此,请确保您没有违反外键约束。这是您问题的最可能原因,尽管这意味着您已经在其他数据库中看到过这些问题。在您的代码中寻找类似这样的模式:

    # in pagetree/models.py, line 810
    @classmethod
    def create_from_dict(cls, d):
        return cls.objects.create()  # what happens to d by the way?
    

    这肯定会因外键约束错误而失败,因为 PageBlock 必须具有 section,因此您不能在不先分配它的情况下调用 create

  2. 如果您通过执行原子事务(例如)来延迟提交外键来规避外键约束,则您的外键需要初始延迟。实际上,您的测试数据库应该已经有了,因为它每次都会重建。

我遇到了同样错误的不同情况。问题是我使用了相同的模型名称和字段名称

错误代码:

class Column(models.Model):
    ...

class ColumnToDepartment(models.Model):
    column = models.ForeignKey(Column, on_delete=models.CASCADE)

解决方案:

class Column(models.Model):
    ...

class ColumnToDepartment(models.Model):
    referring_column = models.ForeignKey(Column, on_delete=models.CASCADE)

我刚刚遇到这个错误:sqlite3.IntegrityError: FOREIGN KEY constraint failed 在我的 Django 项目中。结果我删除了沿线某处的迁移文件夹,所以当我 运行 python manage.py makemigrations 时它没有接收到我的模型更改。只要确保您仍然有一个包含迁移的迁移文件夹。

还有一件事要检查,在我的例子中,它与我的灯具文件有关。 在迁移到 Django3 后重新生成它们解决了我在测试我的应用程序时遇到的问题。

./manage.py dumpdata app.Model1 app.Model2 --indent=4 > ./app/fixtures/file.json

当我在迁移或表方面遇到问题时,我会这样做并且通常会有所帮助:

  1. 评论你的问题字符串;
  2. 执行 python3 manage.py makemigrationspython3 manage.py migrate;
  3. 那么你必须做 python3 manage.py migrate --fake;
  4. 取消注释您的字符串并重做 python3 manage.py makemigrationspython3 manage.py migrate

希望对你有用

就我而言,我发现我的模型引用的 ForeignKey 对象不存在。 所以我只是将引用的 FK 对象更改为存在对象。

迁移后我的问题解决了,因为我更改了外键然后没有应用迁移。

具体来说,起初我在模型中有如下一段代码:

class TeacherRequest(models.Model):
    requester = models.ForeignKey(
        Profile,
        on_delete=models.CASCADE,
        related_name="teacher_request",
    )

    class RequestStatus(models.TextChoices):
        PENDING = '1', _('pending')
        APPROVED = '2', _('approved')
        REJECTED = '3', _('rejected')

    status = models.CharField(
        choices=RequestStatus.choices,
        max_length=1,
        default=RequestStatus.PENDING,
    )

然后我将外键从 Profile 更改为 User:


class TeacherRequest(models.Model):
    requester = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="teacher_request",
    )

    class RequestStatus(models.TextChoices):
        PENDING = '1', _('pending')
        APPROVED = '2', _('approved')
        REJECTED = '3', _('rejected')

    status = models.CharField(
        choices=RequestStatus.choices,
        max_length=1,
        default=RequestStatus.PENDING,
    )

解决方案

python manage.py makemigrations
python manage.py migrate

一个原因可能是您错误地计算了当您从数据库中删除一个项目时会发生什么,该项目与外键链接到其他地方。

p.e。当您删除拥有活跃图书的作者时会发生什么?

我无意进入应用程序的逻辑,但考虑例如 cascade 删除链接到该键的元素。

这是一个示例,在本例中我们处理每个“用户”的“post”属性

user = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE)

这里仔细解释一下,Django 4.0: https://docs.djangoproject.com/en/4.0/ref/models/fields/