Django 2.0:sqlite IntegrityError:外键约束失败
Posted
技术标签:
【中文标题】Django 2.0:sqlite IntegrityError:外键约束失败【英文标题】:Django 2.0: sqlite IntegrityError: FOREIGN KEY constraint failed 【发布时间】:2018-05-17 03:48:12 【问题描述】:我正在努力将 Django 2.0 支持添加到 django-pagetree 库。在自动化测试期间,使用 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
【问题讨论】:
【参考方案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?
这肯定会因为 ForeignKey 约束错误而失败,因为 PageBlock
必须有 section
,所以你不能在没有先分配它的情况下调用 create
。
如果您通过执行原子事务(例如)延迟提交外键来规避外键约束,则您的外键需要初始延迟。事实上,你的测试数据库应该已经有了,因为它每次都重建。
【讨论】:
感谢您的深入研究,我认为您在这里发现了一个错误 -d
应该传递给 cls.objects.create()
。【参考方案2】:
A 遇到了一些不同的情况,但出现了相同的错误。问题是我使用相同的模型名称和字段名称
不正确的代码
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)
【讨论】:
这对我很有帮助!在看到这个答案之前,我完全不知所措...... Django 处理多表继承的方式意味着在你的类层次结构中引入了几个属性,这些属性对应于你的子类的降级名称。如果您没有意识到这一点,它可能会让您认为您的代码有一个奇怪的行为。【参考方案3】:您是否已将 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
【讨论】:
是的,我的模型文件和迁移都有,所以我认为这不是问题所在。如果你有兴趣,我目前的 django 2.0 diff 在这里:github.com/ccnmtl/django-pagetree/pull/187/files 这个确实帮助了我。我将on_delete
属性设置为DO_NOTHING
,这最终违反了外键约束。将其设置为 SET_NULL
为我修复了它。【参考方案4】:
在我的例子中,我发现我的模型引用的 ForeignKey 对象不存在。 所以我只是将引用的 FK 对象更改为存在对象。
【讨论】:
【参考方案5】:我的 Django 项目中出现了这个错误:sqlite3.IntegrityError: FOREIGN KEY constraint failed
。结果我删除了沿线某处的迁移文件夹,因此当我运行python manage.py makemigrations
时它没有接收到我的模型更改。只要确保您仍然有一个包含迁移的迁移文件夹。
【讨论】:
【参考方案6】:还有一件事要检查,在我的情况下,它与我的装置文件有关。 迁移到 Django3 后重新生成它们解决了我在测试我的应用程序时遇到的问题。
./manage.py dumpdata app.Model1 app.Model2 --indent=4 > ./app/fixtures/file.json
【讨论】:
【参考方案7】:当我在迁移或表格方面遇到问题时,我会这样做,这通常会有所帮助:
-
评论您的问题字符串;
做
python3 manage.py makemigrations
和python3 manage.py migrate
;
那你一定要python3 manage.py migrate --fake
;
取消注释您的字符串,然后再次执行 python3 manage.py makemigrations
和 python3 manage.py migrate
。
希望对你有用
【讨论】:
【参考方案8】:迁移后我的问题解决了,因为我更改了外键,然后没有应用迁移。
具体来说,起初我在模型中有以下代码:
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
【讨论】:
以上是关于Django 2.0:sqlite IntegrityError:外键约束失败的主要内容,如果未能解决你的问题,请参考以下文章