一尘不染

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

django

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

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

现在,我开始使用迁移,并且不赞成使用此行为:

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

在官方文件并没有对如何做一个明显的例子,所以我的问题是:

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

  1. 通过多次调用编写Python代码mymodel.create(...)
  2. 使用或编写Django函数(如调用loaddata)从JSON固定文件加载数据。
    我更喜欢第二种选择。

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


阅读 406

收藏
2020-03-27

共1个答案

一尘不染

假设你有一个夹具文件 /fixtures/initial_data.json

创建空迁移:

在Django 1.7中:

python manage.py makemigrations --empty <yourapp>

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

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

编辑你的迁移文件 <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。最简单的:调用loaddata与app_label从将加载器具的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从所有应用程序的夹具目录(你可能不希望这样做)中加载文件名。

运行

python manage.py migrate <yourapp>
2020-03-27