Django 2.0:sqlite完整性错误:外键约束失败

19

我正在为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测试db会创建具有适当选项的db,对吗?我用于测试的应用程序设置在这里:https://github.com/ccnmtl/django-pagetree/blob/master/runtests.py

也许你缺少了外键关系元素。在模型中,你应该已经创建了所有被标记为外键的元素。 - Bip Lob
11个回答

9

我遇到了一个和之前一样的错误,但情况不同。问题在于我使用了相同的模型名称和字段名称。

错误的代码:

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)

这个有解释吗?Python是区分大小写的...但我猜SQLite不是,这就是问题所在吗? - undefined

9

文档中提到了两件事:

  1. If you have ForeignKey constraints they are now enforced at the database level. So make sure you're not violating a foreign key constraint. That's the most likely cause for your issue, although that would mean you'd have seen these issues with other databases. Look for patterns like this in your code:

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

    This will definitely fail with a ForeignKey constraint error since a PageBlock must have section, so you can't call create without first assigning it.

  2. If you circumvent the foreign key constraint by performing an atomic transaction (for example) to defer committing the foreign key, your Foreign Key needs to be INITIALLY DEFERRED. Indeed, your test db should already have that since it's rebuilt every time.


感谢您的深入挖掘,我认为您在这里发现了一个错误 - d 应该传递给 cls.objects.create() - nnyby

2

是的,我已经对我的模型文件和迁移进行了修改,所以我不认为这是问题所在。如果您感兴趣,我的当前django 2.0差异在这里:https://github.com/ccnmtl/django-pagetree/pull/187/files - nnyby
2
这个真的帮到了我。我的 on_delete 属性被设置为 DO_NOTHING,导致违反了外键约束。将它设置为 SET_NULL 对我来说解决了问题。 - Kim Palao

2

在我的情况下,我发现我的模型引用的ForeignKey对象不存在。因此,我将引用的FK对象更改为现有对象。


1
一个可能的原因是你没有正确计算当你从数据库删除一个与其他地方关联的外键时会发生什么。
例如,当你删除一个有活动书籍的作者时会发生什么?
我不是要进入应用程序的逻辑,但考虑例如级联删除与该键相关的元素。
这里是一个例子,在这种情况下我们处理每个用户的“帖子”属性。
user = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE)

以下是关于Django 4.0的详细说明: https://docs.djangoproject.com/en/4.0/ref/models/fields/

0

还有一件事需要检查,就是我的测试数据文件。 在迁移到Django3后重新生成它们可以解决我在测试应用程序时遇到的问题。

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

0

当我在迁移或表格方面遇到问题时,我通常会这样做,它很有效:

  1. 注释掉你的问题字符串;
  2. 运行 python3 manage.py makemigrationspython3 manage.py migrate
  3. 然后你必须运行 python3 manage.py migrate --fake
  4. 取消注释并再次运行 python3 manage.py makemigrationspython3 manage.py migrate

希望对你有用。


0
我刚刚遇到了这个错误:sqlite3.IntegrityError: FOREIGN KEY constraint failed,这是在我的Django项目中发生的。结果发现我在某个地方删除了迁移文件夹,所以当我运行python manage.py makemigrations时,它没有捕捉到我的模型更改。请确保您仍然拥有一个包含迁移文件的迁移文件夹。

0

错误的原因很可能是您的模型中缺少匹配的外键元素,而您正在尝试保存(使用该外键更新)的数据中存在这些元素。 请确保在您的数据和新数据中都存在外键约束(值)。


0

我遇到了一个不同的情况,但是错误却相同。

问题在于我的on_delete属性被设置为DO_NOTHING,这最终导致了违反外键约束

将其设置为SET_NULL对我来说解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接