问题 django在向后迁移/ loaddata之后从fixture加载数据是使用模型模式而不是数据库模式


我在导入旧数据时遇到问题,而不是我当前的模型架构。我使用的流程导致错误:

  • dumpdata with python manage.py dumpdata - > 0002
  • 对模型做一些修改
  • 使用python manage.py schemamigration app_name --auto - > 0003生成迁移
  • 运行迁移
  • 玩数据库
  • 迁移到0002
  • loaddata生成SQL,其中我有当前(迁移0003)字段,并导致loaddata进程失败(mpoly是添加字段)
  File "/usr/local/lib/python2.6/dist-packages/django/db/backends/postgresql_psycopg2/base.py",

第44行,执行中           return self.cursor.execute(query,args)       DatabaseError:关系“localization_province”的列“mpoly”   不存在       第1行:......“”(“id”,“name”,“slug”,“mpoly”)V ...

  • 评论在0003之前完成的models.py中的更改,使所有工作正常

如果我想加载数据,有没有办法避免在向后迁移后使用模型?

也许我错过了一些非常明显的东西......

PS:我使用South 7.3,Django 1.2.3和PostgreSQL 8.4作为数据库后端。


1279
2018-03-29 13:02


起源



答案:


Alex Vidal 当我们把工作归咎于我们时,提出了一个很好的快速解决方案。它需要加里伯恩哈特 Dingus 图书馆。一旦我们有时间,我们将分解出Dingus依赖关系并向South提交拉取请求,但是如果你现在处于绑定状态,这可能会让你失去它:

from dingus import patch


def loaddata(orm, fixture_name):
    _get_model = lambda model_identifier: orm[model_identifier]

    with patch('django.core.serializers.python._get_model', _get_model):
        from django.core.management import call_command
        call_command("loaddata", fixture_name)

用法:

from apps.common.utils import loaddata


class Migration(DataMigration):
    def forwards(self, orm):
        loaddata(orm, "initial_fjords.json")

到目前为止,我们只在Django 1.3中进行了测试。 编辑:我检查了Django的 _get_model 历史,这应该适用于Django 0.95及以上。


10
2018-05-06 02:45



谢谢你的回答。我们使用模拟库(不是dingus),它非常好用。 - guettli
谢谢!它完美地工作并解决了许多数据迁移问题。 - JeromeParadis


答案:


Alex Vidal 当我们把工作归咎于我们时,提出了一个很好的快速解决方案。它需要加里伯恩哈特 Dingus 图书馆。一旦我们有时间,我们将分解出Dingus依赖关系并向South提交拉取请求,但是如果你现在处于绑定状态,这可能会让你失去它:

from dingus import patch


def loaddata(orm, fixture_name):
    _get_model = lambda model_identifier: orm[model_identifier]

    with patch('django.core.serializers.python._get_model', _get_model):
        from django.core.management import call_command
        call_command("loaddata", fixture_name)

用法:

from apps.common.utils import loaddata


class Migration(DataMigration):
    def forwards(self, orm):
        loaddata(orm, "initial_fjords.json")

到目前为止,我们只在Django 1.3中进行了测试。 编辑:我检查了Django的 _get_model 历史,这应该适用于Django 0.95及以上。


10
2018-05-06 02:45



谢谢你的回答。我们使用模拟库(不是dingus),它非常好用。 - guettli
谢谢!它完美地工作并解决了许多数据迁移问题。 - JeromeParadis


我发现最好保留我所拥有的任何灯具与当前版本的代码一致。所以在创建迁移0003时,你会做一个 数据迁移 和一个新的 dumpdata更换夹具0002.当您创建数据迁移时,请确保同时执行前向和后退,这样,当您迁移回0002时,您将获得正确的数据。

执行数据迁移时,请确保通过以下方式访问所有模型 orm 对象,否则你最终会遇到类似于你已经遇到的错误。

如果由于某种原因想要使用旧数据(版本0002)实际运行django代码,那么您的模型需要匹配您的数据库。这意味着使用您正在使用的任何代码版本(git,hg,svn ...)检出适当版本的代码。如果你试图“及时”解决问题,你可能也希望在那时进行分支。

也可以看看 南方的文件评论固定装置

这是一个想法,受上述链接的启发:“最好的办法是编写一个新的迁移来加载夹具”。如何从迁移中加载您的夹具(您已经拥有),而不是 loaddata。您仍然需要创建数据迁移并使用 orm 用于手动加载数据的对象。你可以使用django的 序列化功能,这正是什么 loaddata 

关于为什么 loaddata 使用模型版本而不是数据库版本: loaddata 是一个 django管理命令,不知道南方在做什么。因此,它需要保持数据库不可知并使用django的ORM。你可以随时 编写自己的管理命令 如果你需要做一些更具体的事情 - 可能会删除一些南方的orm版本,或者做一个直接从数据库中读取模式的数据库特定的loaddata。我认为前一段中的解决方案将会少得多。


3
2018-03-29 17:41



我明白了你的方式。但我真的不喜欢它,因为在我的情况下每个转储超过25MB。为我创建的每次迁移准备datadump简直不方便。 - lechup
我仍然没有看到WHY LOADDATA从model.py获取字段而不是简单地为fixture中的数据创建正确的SQL命令? - lechup
我用一些进一步的想法编辑答案。希望有助于清理事情? - meshantz
这句话:“因此,它需要保持数据库不可知并使用django的ORM。”告诉我一切!我刚刚得出这样的结论......我想分享我的想法,但我发现你更快。谢谢! - 我会回复我决定使用的解决方案。 - lechup
我找到了机票 south.aeracode.org/ticket/334 他们想要启用假的orm loaddata。但里程碑1.0是如此遥远。也许如果在本周末不能简单地完成,我会做研究...... - lechup


在讨论的后期,但希望这是有帮助的。你真的可以采取两种方法:

  • 在迁移的早期加载数据,然后使用数据 迁移以在您进行架构迁移时进行更改。这样做的好处是,您可以随时测试数据迁移。

  • 将数据作为夹具加载,它将始终使用您当前的模型 因此要求您保持最新的固定装置。

除了上面的方法之外,您还可以使用dumpscript(作为django-command-extensions的一部分提供)来加载数据,以便在python中转储您的fixture。从那里你需要编辑夹具以使用迁移中可用的ORM,而不是你的Django模型。如果您没有太多数据,这通常最有用。

看到: http://south.aeracode.org/attachment/ticket/1010/fixtures.diff


2
2017-12-05 02:45