首页 文章

如何正确加载Django南迁移中的灯具?

提问于
浏览
4

我正在使用Django 1.5b1和南部迁移,生活一般都很棒 . 我有一些架构更新,用于创建我的数据库,其中包括User表 . 然后我为 ff.User (我的自定义用户模型)加载了一个夹具:

def forwards(self, orm):
        from django.core.management import call_command
        fixture_path = "/absolute/path/to/my/fixture/load_initial_users.json"
        call_command("loaddata", fixture_path)

一直都很好,直到我在我的 ff.User 模型中添加了另一个字段,远离迁移线 . 我的夹具负载现在中断:

DatabaseError: Problem installing fixture 'C:\<redacted>create_users.json':
Could not load ff.User(pk=1): (1054, "Unknown column 'timezone_id' in 'field list'")

Timezone是我添加到用户模型的字段(ForeignKey) .

ff.User与数据库中的不同,因此Django ORM放弃了DB错误 . 不幸的是,我无法在我的夹具中将我的模型指定为 orm['ff.User'] ,这似乎是南方的做事方式 .

我应该如何使用南方正确加载灯具,以便一旦这些灯具的模型被修改后它们不会断开?

6 回答

  • 1

    我找到了一个可以完成这项工作的Django代码片段!

    https://djangosnippets.org/snippets/2897/

    它根据夹具中冻结的模型加载数据,而不是应用程序代码中的实际模型定义!适合我的作品 .

  • 5

    我提出了一个你可能感兴趣的解决方案:

    https://stackoverflow.com/a/21631815/797941

    基本上,这是我加载我的夹具的方式:

    from south.v2 import DataMigration
    import json
    
    class Migration(DataMigration):
    
        def forwards(self, orm):
            json_data=open("path/to/your/fixture.json")
            items = json.load(json_data)
            for item in items:
                # Be carefull, this lazy line won't resolve foreign keys
                obj = orm[item["model"]](**item["fields"])
                obj.save()
    
            json_data.close()
    
  • 0

    这也是我使用灯具的一个令人沮丧的部分 . 我的解决方案是制作一些辅助工具 . 通过从数据库中采样数据来创建灯具,并在灯具中包含南移民历史 .

    还有一个工具可以将南迁移历史记录添加到现有设备中 .

    第三个工具在修改此夹具时检出提交,加载夹具,然后检出最近的提交并执行向南迁移并将迁移的数据库转储回夹具 . 这是在一个单独的数据库中完成的,因此您的默认数据库不会被踩踏 .

    前两个可以被认为是beta代码,第三个可以视为可用的alpha,但它们已经对我很有帮助 .

    很想从别人那里得到一些反馈:git@github.com:JivanAmara / django_fixture_tools.git目前,它只支持使用git作为RCS的项目 .

  • 0

    我找到的最优雅的解决方案是here,其中你的应用模型的 get_model 功能被切换出来,而不是从提供的orm提供模型 . 然后在应用夹具后将其设置回来 .

    from django.db import models
    from django.core.management import call_command
    
    def load_fixture(file_name, orm):
        original_get_model = models.get_model
    
        def get_model_southern_style(*args):
            try:
                return orm['.'.join(args)]
            except:
                return original_get_model(*args)
    
        models.get_model = get_model_southern_style
        call_command('loaddata', file_name)
        models.get_model = original_get_model
    

    您可以使用 load_fixture('my_fixture.json', orm) 从您的转发定义中调用它 .

  • -1

    通常,South使用 forwards()backwards() 函数处理迁移 . 在你的情况下,你应该:

    • 更改灯具以包含正确的数据,或
      迁移前的
    • import fixture会破坏它(或在同一个迁移中,但在更改模式之前),

    在第二种情况下,在迁移添加(或者,在您的情况下,删除)列之前,您应该执行将与此类似地显式加载灯具的迁移(docs):

    def forwards(self, orm):
        from django.core.management import call_command
        call_command("loaddata", "create_users.json")
    

    我相信这是完成你所需要的最简单的方法 . 还要确保在执行较旧的迁移之前,不要尝试使用新结构导入数据等一些简单的错误 .

  • -1

    阅读以下两篇文章帮助我找到了解决方案:

    http://andrewingram.net/2012/dec/common-pitfalls-django-south/#be-careful-with-fixtures

    http://news.ycombinator.com/item?id=4872596

    具体来说,我重写了我的数据迁移以使用'dumpscript'的输出

    我需要修改生成的脚本以便与南方合作 . 而不是做

    from ff.models import User
    

    我做

    User = orm['ff.User']
    

    这与我想要的完全一样 . 此外,它具有不硬编码ID的好处,如灯具要求 .

相关问题