其他应用程序中的Django迁移文件?

2024-04-27 18:03:08 发布

您现在位置:Python中文网/ 问答频道 /正文

让我们设想一个简化的Django项目:

<root>/lib/python2.7/site-packages/externalapp/shop
<root>/myapp

myapp还通过添加几个字段扩展了externalapp.shop.models模型。manage.py makemigrations生成了名为0004_auto_20150410_2001.py的架构迁移文件:

from __future__ import unicode_literals
from django.db import models, migrations


class Migration(migrations.Migration):

    # __init__ is added by me as an attempt how to tell django's
    # migration loader operations are for the different application
    def __init__(self, name, app_label):
        super(Migration, self).__init__(name, 'shop')

    dependencies = [
        ('myapp', '__first__'),
        ('shop', '0003_auto_20150408_0958'),
    ]

    operations = [
        migrations.AddField(
            model_name='product',
            name='vat',
            field=models.ForeignKey(to='myapp.VAT', null=True),
        ),
    ]

如果默认情况下将上述迁移模式放置在<root>/lib/python2.7/site-packages/externalapp/shop/migrations/路径中,manage.py migrate将成功并正确添加表字段。

但是,如果我确实将上述迁移文件移到myapp/migrations/中,则manage.py migrate之后的操作将失败

django.core.management.base.CommandError:检测到冲突迁移(myapp中的0001_initial,0004_auto_20150410_2001)。 要修复它们,请运行“python manage.py makemigrations--merge”

错误消息我无法完全理解,建议makemigrations --merge失败,预期为:

值错误:找不到集合的共同祖先([u'0001_initial',u'0004_auto_20150410_2001'])

我试图重写migrations.Migration.__init__以更改派生的app_label,但似乎迁移加载程序忽略了它。

如何调整迁移文件以便它可以从其他应用程序工作? 原因是在生产中externalapp源不能直接接触,都是只读的。


Tags: 文件djangonamepyautomanageinitmodels
2条回答

要在Django项目周围移动迁移文件,例如在注入其他应用程序的模型时,需要确保在django.db.migrations.Migration子代中:

  • 显式地设置应用程序名,因为迁移加载程序会根据迁移文件所在的应用程序自动派生应用程序名,否则将尝试在不同的模型上执行操作
  • notify migrations recorder它为其他应用程序提供迁移,或者它仍然认为迁移是未应用的(关于应用迁移的记录存储在当前名为django_migrations的表中)

我已经解决了迁移初始值设定项中的问题,它可能看起来像:

from django.db import migrations

TARGET_APP = 'shop'    # application label migration is for

class Migration(migrations.Migration):

    def __init__(self, name, app_label):
        # overriding application operated upon
        super(Migration, self).__init__(name, TARGET_APP)

    # specify what original migration file it replaces
    # or leave migration loader confused about unapplied migration
    replaces = ((TARGET_APP, __module__.rsplit('.', 1)[-1]),)

它确实对我有用,并且找到了足够的通用方法。

如果可能的话,渴望听到更好/更简单的解决方案。

自从Django 1.9以来,就有了MIGRATION_MODULES设置,您可以使用该设置将“外来”模型的迁移拉到您的应用程序中。

FeinCMS docs中所述,在应用程序中创建一个新包(包含__init__.py的文件夹),并在如下设置中列出外部应用程序:

MIGRATION_MODULES = {
    'one': 'yourapp.foreigners.one',
    'other': 'yourapp.foreigners.other',
}

然后你就可以manage.py makemigrations one other

相关问题 更多 >