在迁移文件中使用特定模型时,Django测试失败

时间:2018-03-23 14:06:17

标签: python django django-migrations django-apps

我手动为特定的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内是否存在循环依赖关系,但似乎并非如此。

我在这里缺少什么?

3 个答案:

答案 0 :(得分:1)

我发现来自类似this example的解决方案: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),
    ]

答案 1 :(得分:1)

除非您为其他应用的迁移指定了正确的依赖关系,否则您不应该从迁移文件中的其他应用中触摸模型。基本上,如果您要使用MyOtherModel中的my_other_app,则必须在迁移中向dependencies添加条目,以指向my_other_app中存在MyOtherModel的迁移它处于理想的状态。

&#34;已存在&#34;和#34;期望的状态&#34;这里需要一些解释:当Django处理迁移时,它不会检查当前位于应用程序models.py中的实际模型状态,但是会在创建迁移时尝试从时间点重现模型。因此,如果您要使用some_field中的MyOtherModel,但该字段是在以后的迁移中添加的,则必须至少指向引入此字段的迁移。

同样,如果以后删除了字段,则依赖关系必须指向迁移之前的迁移之一。

请参阅Django文档中的Migrating data between third-party apps

答案 2 :(得分:0)

多亏了这个 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