Django迁移文件在其他应用程序? [英] Django migration file in an other app?

查看:170
本文介绍了Django迁移文件在其他应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面简单介绍一下Django项目:

 < 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆