Django:迁移中的loaddata错误 [英] Django: loaddata in migrations errors

查看:87
本文介绍了Django:迁移中的loaddata错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自从使用Django迁移(不是向南)并在其中的固定装置中使用loaddata以来,我真的很烦。



这里是重现我的简单方法问题:




  • 创建一个新模型 Testmodel ,其中一个字段为 field1 (CharField或其他)

  • 使用<$创建关联的迁移(例如 0001 ) c $ c> makemigrations

  • 运行迁移

  • 并在新表中添加一些数据

  • 将数据转储到夹具 testmodel.json

  • 使用 call_command创建迁移('loaddata','testmodel.json'):迁移 0002

  • 添加一些新字段到模型: field2

  • 创建关联的迁移( 0003



现在,提交该文件,并将您的数据库置于更改之前的状态: ./ manage.py将myapp迁移为零。因此,您所处的状态与尚未更改的队友相同。



如果您尝试运行。/再次进行manage.py migration 时,在迁移0002时您会收到 ProgrammingError ,提示列field2不存在。



似乎是因为loaddata正在研究您的模型(该模型已经具有 field2 ),而不仅仅是将夹具应用于



在团队中工作时可能会在多种情况下发生,并且还会使测试运行程序失败。



我弄错了吗?是虫子吗?在这些情况下应该怎么办?



-



我正在使用Django 1.7

解决方案

loaddata 命令将仅调用序列化程序。序列化器将在您的 models.py 文件中处理模型状态,而不是从当前迁移中进行处理,但是没有什么技巧可以欺骗默认序列化器。



首先,您不想通过 call_command 使用该序列化程序,而是直接使用:



<$来自django.core的p $ p> 导入序列化器

def load_fixture(apps,schema_editor):
Fixture_file ='/full/path/to/testmodel.json'
夹具=打开(fixture_file)
对象= serializers.deserialize('json',夹具,ignorenonexistent = True)
用于对象中的obj:
obj.save()
Fixture.close()

序列化程序使用的第二个,猴子补丁应用程序注册表:

 从django.core导入序列化器

def load_fixture(apps,schema_editor):
original_apps =序列化器.python.apps
serializers.python.apps =应用程序
Fixture_file ='/full/path/to/testmodel.json'
fixt ure =打开(fixture_file)
对象= serializers.deserialize('json',夹具,ignorenonexistent = True)
对于对象中的obj:
obj.save()
夹具。 close()
serializers.python.apps = original_apps

现在,序列化器将使用来自 apps 而不是默认值,整个迁移过程将成功。


Something really annoying is happening to me since using Django migrations (not south) and using loaddata for fixtures inside of them.

Here is a simple way to reproduce my problem:

  • create a new model Testmodel with 1 field field1 (CharField or whatever)
  • create an associated migration (let's say 0001) with makemigrations
  • run the migration
  • and add some data in the new table
  • dump the data in a fixture testmodel.json
  • create a migration with call_command('loaddata', 'testmodel.json'): migration 0002
  • add some a new field to the model: field2
  • create an associated migration (0003)

Now, commit that, and put your db in the state just before the changes: ./manage.py migrate myapp zero. So you are in the same state as your teammate that didn't get your changes yet.

If you try to run ./manage.py migrate again you will get a ProgrammingError at migration 0002 saying that "column field2 does not exist".

It seems it's because loaddata is looking into your model (which is already having field2), and not just applying the fixture to the db.

This can happen in multiple cases when working in a team, and also making the test runner fail.

Did I get something wrong? Is it a bug? What should be done is those cases?

--

I am using django 1.7

解决方案

loaddata command will simply call serializers. Serializers will work on models state from your models.py file, not from current migration, but there is little trick to fool default serializer.

First, you don't want to use that serializer by call_command but rather directly:

from django.core import serializers

def load_fixture(apps, schema_editor):
    fixture_file = '/full/path/to/testmodel.json'
    fixture = open(fixture_file)
    objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
    for obj in objects:
        obj.save()
    fixture.close()

Second, monkey-patch apps registry used by serializers:

from django.core import serializers

def load_fixture(apps, schema_editor):
    original_apps = serializers.python.apps
    serializers.python.apps = apps
    fixture_file = '/full/path/to/testmodel.json'
    fixture = open(fixture_file)
    objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
    for obj in objects:
        obj.save()
    fixture.close()
    serializers.python.apps = original_apps

Now serializer will use models state from apps instead of default one and whole migration process will succeed.

这篇关于Django:迁移中的loaddata错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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