django 在向后迁移/ loaddata 后从夹具加载数据使用的是模型模式而不是数据库模式

Posted

技术标签:

【中文标题】django 在向后迁移/ loaddata 后从夹具加载数据使用的是模型模式而不是数据库模式【英文标题】:django loading data from fixture after backward migration / loaddata is using model schema not database schema 【发布时间】:2011-07-25 06:45:25 【问题描述】:

我最近在导入比我当前模型架构更旧的数据时遇到了一个问题。我使用并导致错误的流程:

dumpdata 与 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 行,执行中 返回 self.cursor.execute(查询,参数) DatabaseError:关系“localization_province”的列“mpoly”确实 不存在 第 1 行:...e" ("id", "name", "slug", "mpoly") V...

评论在 0003 之前完成的 models.py 中的更改,确保一切正常

如果我想加载数据,有什么方法可以避免在向后迁移后玩模型?

也许我遗漏了一些非常明显的东西......

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

【问题讨论】:

【参考方案1】:

Alex Vidal 提出了一个很好的快速解决方案,因为它在我们的工作中咬了我们。它需要 Gary Bernhardt 的 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 及更高版本。

【讨论】:

感谢您的回答。我们使用模拟库(不是 dingus),它工作得非常好。 谢谢!完美运行,解决了很多数据迁移问题。【参考方案2】:

我发现最好让我拥有的所有固定装置与当前版本的代码保持一致。因此,在创建迁移 0003 时,您将执行 data migration 和新的 dumpdata,替换夹具 0002。当您创建数据迁移时,请确保您同时进行前向和后向迁移,这样您最终会得到正确的数据你迁移回 0002。

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

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

另见south's documentation comments on fixtures

这里有一个想法,灵感来自上面的链接:“最好的办法是编写一个新的迁移来加载夹具”。从迁移而不是loaddata 加载您的固定装置(您已经拥有)怎么样。您仍然需要创建数据迁移并使用 orm 对象手动加载数据。你可以使用django的serialization functions,也就是loaddatadoes。

关于loaddata为什么使用模型版本而不是数据库版本:loaddata是django management command,不知道南在做什么。因此,它需要保持与数据库无关并使用 django 的 ORM。如果您需要做一些更具体的事情,您可以随时write your own management command - 可能会提取一些南方的 orm 版本控制,或者执行直接从数据库读取模式的数据库特定加载数据。我认为上一段中的解决方案会少很多工作。

【讨论】:

我明白你的意思。但我不太喜欢它,因为在我的情况下,每个转储都超过 25MB。为我创建的每个迁移准备数据转储是很不方便的。 我仍然看不到为什么 LOADDATA 从 model.py 中获取字段,而不是简单地为来自夹具的数据创建适当的 SQL 命令? 我已经用一些进一步的想法编辑了答案。希望这有助于解决问题? 行:“因此,它需要保持与数据库无关并使用 django 的 ORM。”告诉我一切!我刚刚得出这样的结论......我想分享我的想法,但我看到你更快。谢谢! - 我会回复我决定使用的解决方案。 我在south.aeracode.org/ticket/334 上找到了他们想要启用虚假 orm 加载数据的票证。但里程碑 1.0 还很遥远。如果不能在这个周末简单地完成,也许我会做研究......【参考方案3】:

这个讨论迟到了,但希望这会有所帮助。实际上,您可以采取两种方法:

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

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

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

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

【讨论】:

以上是关于django 在向后迁移/ loaddata 后从夹具加载数据使用的是模型模式而不是数据库模式的主要内容,如果未能解决你的问题,请参考以下文章

Django:迁移错误中的加载数据

为啥在向后滑动时自动旋转无法正常工作?

带有转储数据和迁移的 Django 备份策略

在向后传递中调试 nans

axios.get() 在向后端发送请求时正在组合 url。

pytorch 在向后()中崩溃并冻结屏幕,你能帮帮我吗?