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 无法创建用于单元测试的表