我最近从Django 1.6切换到1.7,并且开始使用迁移功能(我从未使用过South)。
在1.7之前,我曾经用fixture/initial_data.json文件加载初始数据,该文件是用python manage.py syncdb命令加载的(在创建数据库时)。
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)
在官方文件并没有对如何做一个明显的例子,所以我的问题是:
使用数据迁移导入此类初始数据的最佳方法是什么:
mymodel.create(...)
我不想使用South,因为Django现在似乎可以本地使用。
假设你有一个夹具文件 /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
<yourapp>/migrations/0002_auto_xxx.py
2.1。自定义实现,受Django’ loaddata(初始答案)启发:
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从所有应用程序的夹具目录(你可能不希望这样做)中加载文件名。
app_label,loaddata
fixture
运行
python manage.py migrate <yourapp>