其他应用程序中的 Django 迁移文件?
Django migration file in an other app?
让我们想象一个以下简化的 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),
),
]
如果上面的迁移schema默认放在<root>/lib/python2.7/site-packages/externalapp/shop/migrations/
路径下,manage.py migrate
成功,正确添加table字段
但是,如果我将上述迁移文件移动到 myapp/migrations/
,则 manage.py migrate
之后会失败并显示
django.core.management.base.CommandError:检测到迁移冲突(0001_initial,0004_auto_20150410_2001 in myapp)。
修复它们 运行 'python manage.py makemigrations --merge'
错误消息我不太理解并建议 makemigrations --merge
失败,预期:
ValueError: 找不到集合的共同祖先([u'0001_initial', u'0004_auto_20150410_2001'])
我试图覆盖 migrations.Migration.__init__
以改变派生 app_label
但迁移加载器似乎忽略了它。
如何调整迁移文件使其可以在其他应用程序中运行?
原因是在生产中 externalapp
源不能直接接触,是只读的。
要围绕 Django 项目移动迁移文件,就像注入其他应用程序的模型一样,您需要确保在您的 django.db.migrations.Migration
后代中:
- 显式设置应用程序名称,因为迁移加载程序由迁移文件所在的应用程序自动派生它,否则将尝试在不同模型上执行操作
- 通知迁移记录器它为其他应用程序提供迁移,否则它仍会将迁移视为未应用(有关已应用迁移的记录存储在 table,当前名为
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]),)
它确实对我有用,并且发现它足够通用。
如果可能,很想知道 better/simpler 解决方案。
从 Django 1.9 开始,您可以使用 MIGRATION_MODULES
设置将 "foreign" 模型迁移到您的应用程序中。
如 FeinCMS docs 中所述,您在您的应用程序中创建一个新程序包(带有 __init__.py
的文件夹)并在设置中列出外国应用程序,如下所示:
MIGRATION_MODULES = {
'one': 'yourapp.foreigners.one',
'other': 'yourapp.foreigners.other',
}
之后你可以manage.py makemigrations one other
等等
让我们想象一个以下简化的 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),
),
]
如果上面的迁移schema默认放在<root>/lib/python2.7/site-packages/externalapp/shop/migrations/
路径下,manage.py migrate
成功,正确添加table字段
但是,如果我将上述迁移文件移动到 myapp/migrations/
,则 manage.py migrate
之后会失败并显示
django.core.management.base.CommandError:检测到迁移冲突(0001_initial,0004_auto_20150410_2001 in myapp)。 修复它们 运行 'python manage.py makemigrations --merge'
错误消息我不太理解并建议 makemigrations --merge
失败,预期:
ValueError: 找不到集合的共同祖先([u'0001_initial', u'0004_auto_20150410_2001'])
我试图覆盖 migrations.Migration.__init__
以改变派生 app_label
但迁移加载器似乎忽略了它。
如何调整迁移文件使其可以在其他应用程序中运行?
原因是在生产中 externalapp
源不能直接接触,是只读的。
要围绕 Django 项目移动迁移文件,就像注入其他应用程序的模型一样,您需要确保在您的 django.db.migrations.Migration
后代中:
- 显式设置应用程序名称,因为迁移加载程序由迁移文件所在的应用程序自动派生它,否则将尝试在不同模型上执行操作
- 通知迁移记录器它为其他应用程序提供迁移,否则它仍会将迁移视为未应用(有关已应用迁移的记录存储在 table,当前名为
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]),)
它确实对我有用,并且发现它足够通用。
如果可能,很想知道 better/simpler 解决方案。
从 Django 1.9 开始,您可以使用 MIGRATION_MODULES
设置将 "foreign" 模型迁移到您的应用程序中。
如 FeinCMS docs 中所述,您在您的应用程序中创建一个新程序包(带有 __init__.py
的文件夹)并在设置中列出外国应用程序,如下所示:
MIGRATION_MODULES = {
'one': 'yourapp.foreigners.one',
'other': 'yourapp.foreigners.other',
}
之后你可以manage.py makemigrations one other
等等