Django:在运行单元测试之前创建测试表时“无法添加外键约束”

Posted

技术标签:

【中文标题】Django:在运行单元测试之前创建测试表时“无法添加外键约束”【英文标题】:Django: "Cannot add foreign key constraint" when creating test tables before running unit tests 【发布时间】:2018-10-01 09:40:45 【问题描述】:

我正在尝试运行我为 Django 项目编写的单元测试,但在数据库创建阶段测试失败。我有一个单一的数据库“测试”,其中一个作为与另一个的外键关系。我运行以下命令:

python3 manage.py test --settings myapp.settings_test

并查看以下输出:

Creating test database for alias 'test'...
Got an error creating the test database: (1007, "Can't create database 'test_test'; database exists")
Type 'yes' if you would like to try deleting the test database 'test_test', or 'no' to cancel: yes
Destroying old test database for alias 'test'...
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python3.5/dist-packages/django/db/backends/mysql/base.py", line 71, in execute
    return self.cursor.execute(query, args)
  File "/usr/local/lib/python3.5/dist-packages/MySQLdb/cursors.py", line 250, in execute
    self.errorhandler(self, exc, value)
  File "/usr/local/lib/python3.5/dist-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
    raise errorvalue
  File "/usr/local/lib/python3.5/dist-packages/MySQLdb/cursors.py", line 247, in execute
    res = self._query(query)
  File "/usr/local/lib/python3.5/dist-packages/MySQLdb/cursors.py", line 411, in _query
    rowcount = self._do_query(q)
  File "/usr/local/lib/python3.5/dist-packages/MySQLdb/cursors.py", line 374, in _do_query
    db.query(q)
  File "/usr/local/lib/python3.5/dist-packages/MySQLdb/connections.py", line 277, in query
    _mysql.connection.query(self, query)
_mysql_exceptions.IntegrityError: (1215, 'Cannot add foreign key constraint')

我见过很多这样的答案:Django MySQL error when creating tables。

这样的答案表明,一般来说,这个错误是由于在添加外键引用的表之前添加了具​​有外键字段的表引起的。但是,对于如何在测试场景中解决这个问题,我没有找到很多有用的答案。

我尝试过的其他事情:

我尝试在 Django shell 中运行测试,然后我可以使用“django.db.connection”来显示 Django 正在运行的原始 MySQL 命令,但我似乎无法弄清楚如何在 Django shell 中运行测试。

我尝试在没有迁移的情况下运行测试 (https://pypi.org/project/django-test-without-migrations/),但这似乎没有效果。

在我的测试设置文件中,我添加了 MIGRATION_MODULES 变量来处理具有外键字段的应用“badapp”:

迁移模块 = 'badapp':无

但这也没什么区别。

我想知道:

1.) 如何验证此错误是由于添加表的顺序不正确造成的?

2.) 如何在运行测试时强制按特定顺序添加表?

【问题讨论】:

【参考方案1】:

根据您的reddit version of the question,您在数据库选项中设置了'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"。当你删除它时会发生什么?你的默认存储引擎是什么(我假设是 InnoDB 但想检查一下)?

【讨论】:

默认存储引擎确实是InnoDB。当我从数据库定义中删除 options 参数时,没有任何变化。【参考方案2】:

如果您指定的自定义 MIGRATION_MODULES 条目指向不包含 __init__.py 的路径,则可能会发生此错误。

【讨论】:

【参考方案3】:

在我的情况下是迁移问题,我运行

python manage.py test --verbosity=3

为了检查执行跟踪,在验证跟踪后我可以看到我的模型的表没有被创建,所以我执行了

python manage.py makemigrations

并且可以完美运行测试需要注意的是我的模型没有外键,所以报错比较奇怪。

【讨论】:

以上是关于Django:在运行单元测试之前创建测试表时“无法添加外键约束”的主要内容,如果未能解决你的问题,请参考以下文章

从 1.8 升级到 2.2.4 后,Django 无法创建用于单元测试的表

每次运行时都没有创建测试数据库的 Django 单元测试

Django 中单元测试的覆盖设置无法正常工作

无法为 Django 的重置密码流程创建集成测试

无法在 Visual Studio 2013 中运行单元测试

用于创建数据库、运行测试的 Django / postgres 设置