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

发布于 2024-10-27 14:04:39 字数 854 浏览 4 评论 0原文

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

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

第44行,执行中 返回 self.cursor.execute(查询,参数) 数据库错误:关系“localization_province”的列“mpoly”确实 不存在 第 1 行:...e" ("id", "name", "slug", "mpoly") V...

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

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

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

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

I have recenty came across a problem while importing older data than my current model schema. Flow which I use and lead to error:

  • dumpdata with python manage.py dumpdata -> 0002
  • make some modifications to model
  • generate migration with python manage.py schemamigration app_name --auto -> 0003
  • run migration
  • play with database
  • migrate to 0002
  • loaddata generate SQL in which I have current (migration 0003) fields, and cause failing loaddata process (mpoly is added field)
  File "/usr/local/lib/python2.6/dist-packages/django/db/backends/postgresql_psycopg2/base.py",

line 44, in execute
return self.cursor.execute(query, args)
DatabaseError: column "mpoly" of relation "localization_province" does
not exist
LINE 1: ...e" ("id", "name", "slug", "mpoly") V...

  • commenting changes in models.py done before 0003, make all working ok

Is there any way to avoid playing with models after backward migration if I want to loaddata?

Maybe I'm missing something really obvious...

PS: I'm using South 7.3, Django 1.2.3 and PostgreSQL 8.4 as database backend.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

天赋异禀 2024-11-03 14:04:39

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 及更高版本。

Alex Vidal proposed a nice quick fix for this when it bit us at our job. It requires Gary Bernhardt's Dingus library. Once we have time we'll factor out the Dingus dependency and submit a pull request to South, but if you're in a bind right now this may get you out of it:

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)

Usage:

from apps.common.utils import loaddata


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

We've tested only in Django 1.3 so far. Edit: I checked Django's _get_model history and this should work with Django 0.95 and up.

饮惑 2024-11-03 14:04:39

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

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

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

另请参阅 south 关于装置的文档注释

这是一个受上面链接启发的想法:“最好的办法是编写一个新的迁移来加载固定装置”。从迁移中加载您的固定装置(您已经拥有的)而不是 loaddata 怎么样?您仍然需要创建数据迁移并使用 orm 对象手动加载数据。您可以使用 django 的 序列化函数,这正是 loaddata 确实

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

I find that it is best to keep any fixtures I have in line with the current version of the code. So upon creating migration 0003 you do a data migration and a new dumpdata, replacing fixture 0002. When you create your data migration, make sure you do both forwards and backwards, that way you'll end up with the correct data when you migrate back to 0002.

When you do the data migration, make sure you access all models through the orm object, otherwise you end up with errors similar to what you're already experiencing.

If you want to actually run your django code with the old data (version 0002) for some reason, then your models need to match your database. That would mean checking out an appropriate version of the code using whatever code versioning you're using (git, hg, svn...). If you're trying to solve a problem "back in time" you probably want to branch at that point too.

See also south's documentation comments on fixtures

Here's an idea, inspired by that link above: "the best thing to do is to write a new migration to load the fixture in". What about loading your fixture (which you already have) from a migration, rather than loaddata. You would still need to create a data migration and use the orm object to manually load the data. You can make use of django's serialization functions, which is exactly what loaddata does.

With respect to why loaddata uses the model version and not the database version: loaddata is a django management command, with no knowledge of what south is doing. Because of that, it needs to remain database agnostic and use django's ORM. You can always write your own management command if you need to do something more specific - potentially pulling out some of south's orm versioning, or doing a database specific loaddata that reads the schema directly from the database. I think the solution in the previous paragraph will be a lot less work though.

提笔书几行 2024-11-03 14:04:39

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

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

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

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

请参阅:http://south.aeracode.org/attachment/ticket/1010/fixtures .diff

Late to this discussion but hope this is helpful. Really you have two approaches you can take:

  • Load the data early on in your migrations and then use data
    migrations to change it any time you have a schema migration. This has the advantage that you are testing your data migrations as you go.

  • Load the data as a fixture, which will always use your current models
    and therefore require you to keep your fixtures up to date.

In addition to the approaches above, you can load data by using dumpscript (available as part of django-command-extensions) to dump out your fixture in python. From there you need to edit the fixture to use the ORM available within the migration, rather than your Django models. This is usually most useful if you don't have too much data.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文