使用 Django 1.7 加载初始数据和数据迁移 [英] Loading initial data with Django 1.7 and data migrations

查看:35
本文介绍了使用 Django 1.7 加载初始数据和数据迁移的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I recently switched from Django 1.6 to 1.7, and I began using migrations (I never used South).

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

Before 1.7, I used to load initial data with a fixture/initial_data.json file, which was loaded with the python manage.py syncdb command (when creating the database).

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

Now, I started using migrations, and this behavior is deprecated :

如果应用程序使用迁移,则不会自动加载夹具.由于 Django 2.0 中的应用程序需要迁移,因此此行为被视为已弃用.如果要为应用加载初始数据,请考虑在数据迁移中进行.(https://docs.djangoproject.com/en/1.7/howto/initial-data/#automatically-loading-initial-data-fixtures)

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)

官方文档没有明确的例子关于如何做到这一点,所以我的问题是:

The official documentation does not have a clear example on how to do it, so my question is :

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

What is the best way to import such initial data using data migrations :

  1. 编写多次调用 mymodel.create(...) 的 Python 代码,
  2. 使用或编写 Django 函数(比如调用 loaddata) 从 JSON 夹具文件加载数据.
  1. Write Python code with multiple calls to mymodel.create(...),
  2. Use or write a Django function (like calling loaddata) to load data from a JSON fixture file.

我更喜欢第二个选项.

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

I don't want to use South, as Django seems to be able to do it natively now.

推荐答案

更新:请参阅下方@GwynBleidD 的评论,了解此解决方案可能导致的问题,并参阅下方@Rockallite 的回答,了解更多经得起未来模型变化的考验.

Update: See @GwynBleidD's comment below for the problems this solution can cause, and see @Rockallite's answer below for an approach that's more durable to future model changes.

假设您在 <yourapp>/fixtures/initial_data.json

  1. 创建您的空迁移:

  1. Create your empty migration:

在 Django 1.7 中:

In Django 1.7:

python manage.py makemigrations --empty <yourapp>

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

In Django 1.8+, you can provide a name:

python manage.py makemigrations --empty <yourapp> --name load_intial_data

  • 编辑您的迁移文件/migrations/0002_auto_xxx.py

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

    2.1. Custom implementation, inspired by Django' loaddata (initial answer):

    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 的建议):

    2.2. A simpler solution for load_fixture (per @juliocesar's suggestion):

    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.最简单:使用app_label调用loaddata将从fixtures<中加载fixtures/code> 目录自动:

    2.3. Simplest: calling loaddata with app_label will load fixtures from the <yourapp>'s fixtures dir automatically :

    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 将尝试从所有 应用程序装置目录(您可能不想).

    If you don't specify app_label, loaddata will try to load fixture filename from all apps fixtures directories (which you probably don't want).

    运行它

    python manage.py migrate <yourapp>
    

  • 这篇关于使用 Django 1.7 加载初始数据和数据迁移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆