python - 使用 Django 1.7+ 和数据迁移加载初始数据

我最近从 Django 1.6 切换到 1.7,并开始使用迁移(我从未使用过 South)。

在 1.7 之前,我使用 fixture/initial_data.json 文件加载初始数据,该文件是通过 python manage.py syncdb 命令加载的(在创建数据库)。

现在,我开始使用迁移,这种行为已被弃用:

If an application uses migrations, there is no automatic loading of fixtures. Since migrations will be required for applications in Django 2.0, this behavior is considered deprecated. If you want to load initial data for an app, consider doing it in a data migration. (https://docs.djangoproject.com/en/1.7/howto/initial-data/#automatically-loading-initial-data-fixtures)

official documentation没有一个明确的例子来说明如何做到这一点,所以我的问题是:

使用数据迁移导入此类初始数据的最佳方式是什么:

  1. 编写 Python 代码,多次调用 mymodel.create(...),
  2. 使用或编写 Django 函数 (like calling loaddata) 从 JSON 固定文件加载数据。

我更喜欢第二种选择。

我不想使用 South,因为 Django 现在似乎可以在本地使用它。

最佳答案

更新:请参阅下面@GwynBleidD 的评论,了解此解决方案可能导致的问题,并参阅下面@Rockallite 的回答,了解对 future 模型更改更持久的方法。


假设您在 <yourapp>/fixtures/initial_data.json 中有一个夹具文件

  1. 创建你的空迁移:

    在 Django 1.7 中:

    python manage.py makemigrations --empty <yourapp>
    

    在 Django 1.8+ 中,您可以提供名称:

    python manage.py makemigrations --empty <yourapp> --name load_intial_data
    
  2. 编辑您的迁移文件 <yourapp>/migrations/0002_auto_xxx.py

    2.1。自定义实现,灵感来自 Django' loaddata (初步答案):

    import os
    from sys import path
    from django.core import serializers
    
    fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures'))
    fixture_filename = 'initial_data.json'
    
    def load_fixture(apps, schema_editor):
        fixture_file = os.path.join(fixture_dir, fixture_filename)
    
        fixture = open(fixture_file, 'rb')
        objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
        for obj in objects:
            obj.save()
        fixture.close()
    
    def unload_fixture(apps, schema_editor):
        "Brutally deleting all entries for this model..."
    
        MyModel = apps.get_model("yourapp", "ModelName")
        MyModel.objects.all().delete()
    
    class Migration(migrations.Migration):  
    
        dependencies = [
            ('yourapp', '0001_initial'),
        ]
    
        operations = [
            migrations.RunPython(load_fixture, reverse_code=unload_fixture),
        ]
    

    2.2。 load_fixture 的更简单的解决方案(根据@juliocesar 的建议):

    from django.core.management import call_command
    
    fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures'))
    fixture_filename = 'initial_data.json'
    
    def load_fixture(apps, schema_editor):
        fixture_file = os.path.join(fixture_dir, fixture_filename)
        call_command('loaddata', fixture_file) 
    

    如果你想使用自定义目录很有用。

    2.3。 最简单:调用loaddataapp_label将从 <yourapp> 加载固定装置的fixtures目录自动:

    from django.core.management import call_command
    
    fixture = 'initial_data'
    
    def load_fixture(apps, schema_editor):
        call_command('loaddata', fixture, app_label='yourapp') 
    

    如果您不指定 app_label , loaddata 将尝试加载 fixture all 应用程序装置目录中的文件名(您可能不想要)。

  3. 运行它

    python manage.py migrate <yourapp>
    

https://stackoverflow.com/questions/25960850/

相关文章:

c# - 如何在asp.net mvc中展平通过JsonResult返回的ExpandoObject

javascript - 移除 JSON 元素

javascript - 在 JSON 中,为什么要引用每个名称?

python - JSON中的单引号和双引号

mysql - MYSQL 5.7 中的原生 JSON 支持 : what are the pros

json - 如何在屏幕上显示 JSON 表示而不是 [Object Object]

.net - 您的项目未引用 ".NETFramework,Version=v4.5"框架。

c# - 从 .NET 控制台调用 JSON WebService 的最佳方式

javascript - JSON.parse 与 eval()

javascript - Angular 2 : How do you render HTML fr