Django迁移文件在其他应用程序? [英] Django migration file in an other app?
问题描述
< root> /lib/python2.7/site-packages/ externalapp / shop
< root> / myapp
myapp
还通过添加几个字段来扩展 externalapp.shop.models
模型。 manage.py makemigrations
确实生成了以下模式迁移文件,名为 0004_auto_20150410_2001.py :
从__future__导入unicode_literals
从django.db导入模型,迁移
类迁移(迁移。迁移):
#__init__被我添加为尝试如何告诉django的
#迁移加载程序操作是针对不同的应用程序
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 /
路径中,管理。 py迁移
成功,表字段正确添加。
但是,如果我将上述迁移文件移动到 myapp /迁移/
,跟随 manage.py migrate
失败,
django。 core.management.base.CommandError:检测到冲突的迁移(myapp中的0001_initial,0004_auto_20150410_2001)。
要修复它们运行'python manage.py makemigrations --merge'
错误消息我不太明白并建议 makemigrations --merge
失败与预期:
ValueError:找不到set的共同祖先([u'0001_initial ',u'0004_auto_20150410_2001'])
我试图覆盖 migrations.Migration .__ init __
更改派生的 app_label
,但似乎迁移加载器忽略它。
如何调整迁移文件,使其可以从其他申请?
原因是在生产中 externalapp
源不能被直接触摸,只能被读取。
要在Django项目周围移动迁移文件,例如注入其他应用程序的模型,您需要确保在 django.db.migrations.Migration
descendant:
- 显式设置应用程序名称,因为迁移装载程序会由迁移文件所在的应用程序自动导出,并尝试对不同的模型执行操作,否则
- 通知迁移记录器为其他应用程序提供迁移,或者仍然将迁移视为未应用程序(有关应用迁移的记录存储在表中,目前命名为
django_migrations
)
我已经解决了迁移初始值设置中的问题,
从django.db导入迁移
TARGET_APP ='shop' #application label migration for
class Migration(migrations.Migration):
def __init __(self,name,app_label):
#overriding application operating on
super(Migration,self).__ init __(name,TARGET_APP)
#指定它取代
#的原始迁移文件,或者让迁移加载器对未应用的迁移感到困惑
替换=((TARGET_APP,__module __。rsplit('。',1)[ - 1]),)
<
如果可能,渴望听到更好/更简单的解决方案。
Let's imagine a following simplified Django project:
<root>/lib/python2.7/site-packages/externalapp/shop
<root>/myapp
myapp
also extends externalapp.shop.models
models by adding a few fields. manage.py makemigrations
did generated following schema migration file called 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),
),
]
If the above migration schema is placed in <root>/lib/python2.7/site-packages/externalapp/shop/migrations/
path by default, manage.py migrate
succeeds and table fields are correctly added.
However if I do move the above migration file into myapp/migrations/
, following manage.py migrate
fails with
django.core.management.base.CommandError: Conflicting migrations detected (0001_initial, 0004_auto_20150410_2001 in myapp). To fix them run 'python manage.py makemigrations --merge'
error message I can't quite understand and suggested makemigrations --merge
fails with expected:
ValueError: Could not find common ancestor of set([u'0001_initial', u'0004_auto_20150410_2001'])
I've tried to override migrations.Migration.__init__
to alter derived app_label
but seems migration loader ignores it.
How adjust migration file so it can work from other application ?
The reason is in production externalapp
sources can't be directly touched, are read only.
To move a migration file around a Django project, like in case of injecting models of other applications, you need to ensure in your django.db.migrations.Migration
descendant:
- explicitly set application name, as migrations loader derives it automatically by app where migration file resides and would attempt to perform operations on different models otherwise
- notify migrations recorder it provides migration for other application or it would still consider migration as unapplied (records about applied migrations are stored in a table, currently named
django_migrations
)
I've solved the issue in migration initializer which may look like:
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]),)
It does work for me and find it enough generic way.
Eager to hear about a better/simpler solution if possible.
这篇关于Django迁移文件在其他应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!