在迁移文件中使用特定模型时,Django 测试失败
Posted
技术标签:
【中文标题】在迁移文件中使用特定模型时,Django 测试失败【英文标题】:Django tests fails when using a specific model in a migration file 【发布时间】:2018-09-02 05:43:42 【问题描述】:我已经为特定的 Django 1.11 应用手动创建了数据迁移文件:
from __future__ import unicode_literals
from django.db import migrations, models
def set_item_things(apps, schema_editor):
MyModel = apps.get_model('my_app', 'MyModel')
# NOTE: if I remove this line then the tests will work
MyOtherModel = apps.get_model('my_other_app', 'MyOtherModel')
for item in MyModel.objects.all():
# NOTE: if I remove this line then the tests will work
thingy = MyOtherModel.get(example_field=item.color)
item.other_thing = thingy
item.save()
class Migration(migrations.Migration):
dependencies = [
('contracts', '0014_my_previous_migration'),
]
operations = [
migrations.RunPython(set_item_things),
]
当我运行 python manage.py migrate
时,一切都按预期工作。
但是每当我使用 pytest 运行测试时,我都会得到:
test setup failed
self = <django.db.migrations.state.StateApps object at 0x10714b2b0>
app_label = 'my_other_app'
def get_app_config(self, app_label):
"""
Imports applications and returns an app config for the given label.
Raises LookupError if no application exists with this label.
"""
self.check_apps_ready()
try:
> return self.app_configs[app_label]
E KeyError: 'my_other_app'
所以看起来应用配置没有正确配置,这已经很奇怪了,因为 migrate 命令运行顺利。
不管怎样:这是my_other_app/apps.py
的内容:
from django.apps import AppConfig
class MyOtherAppConfig(AppConfig):
name = 'my_other_app'
基本上与其他应用程序目录中的所有其他apps.py
非常相似,当然名称除外。
所以我认为配置应该是正确的,但无论出于何种原因,我的测试都无法运行。
唯一的解决方法是从迁移文件中删除对my_other_app
的任何引用。
我已经尝试将此添加到my_other_apps/__init__.py
:
default_app_config = 'my_other_apps.apps.MyOtherAppConfig'
但没有任何变化。
我已经尝试查看my_other_apps/models.py
内部是否存在循环依赖关系,但似乎并非如此。
我在这里缺少什么?
【问题讨论】:
【参考方案1】:我从类似的SO question 中找到了解决方案:MyOtherModel
来自不同的应用程序,因此在我的迁移文件中,我必须指定该应用程序最后一次迁移作为附加依赖项,即:
class Migration(migrations.Migration):
dependencies = [
('contracts', '0014_my_previous_migration'),
# THIS extra line solves the problem!
('my_other_app', '002_my_last_migration'),
]
operations = [
migrations.RunPython(set_item_things),
]
【讨论】:
【参考方案2】:您不应在迁移文件中接触来自其他应用的模型,除非您为该其他应用的迁移指定适当的依赖项。基本上,如果您想从my_other_app
使用MyOtherModel
,您必须在迁移中添加dependencies
的条目,以指向my_other_app
中的迁移,其中MyOtherModel
存在并且处于所需状态。
"Exists" 和 "desired state" 在这里需要一些解释:当 Django 处理迁移时,它不会检查当前在您的应用程序的models.py
中的实际模型状态,而是尝试从点重现您的模型及时创建迁移。因此,如果您想使用 MyOtherModel
中的 some_field
,但该字段是在以后的迁移中添加的,您至少必须指向引入该字段的迁移。
同样,如果稍后您的字段被删除,依赖项必须指向该迁移之前的迁移之一。
请参阅 Django 文档中的 Migrating data between third-party apps。
【讨论】:
【参考方案3】:感谢link 来自answer 我在尝试运行 Django 测试时解决了我的问题:
错误
LookupError: App 'old_app' doesn't have a 'OldModel' model.
解决方案
def forwards(apps, schema_editor):
try:
OldModel = apps.get_model('old_app', 'OldModel')
except LookupError:
# The old app isn't installed.
return
【讨论】:
以上是关于在迁移文件中使用特定模型时,Django 测试失败的主要内容,如果未能解决你的问题,请参考以下文章
Django - 将 ForeignKey 关系更改为 OneToOne