Loading initial data with Django 1.7+ and data migrations
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.
Assuming you have a fixture file in
<yourapp>/fixtures/initial_data.json
Create your empty migration:
In Django 1.7:
In Django 1.8+, you can provide a name:python manage.py makemigrations --empty <yourapp>
python manage.py makemigrations --empty <yourapp> --name load_intial_data
Edit your migration file
<yourapp>/migrations/0002_auto_xxx.py
2.1. Custom implementation, inspired by Django'
loaddata
(initial answer):
2.2. A simpler solution forimport 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),
]load_fixture
(per @juliocesar's suggestion):
Useful if you want to use a custom directory.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. Simplest: calling
loaddata
withapp_label
will load fixtures from the<yourapp>
'sfixtures
dir automatically :
If you don't specifyfrom 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 will try to loadfixture
filename from all apps fixtures directories (which you probably don't want).Run it
python manage.py migrate <yourapp>
Populating db with initial data in Django
You can fix the "not reversible" part by making the migration reversible. If you used RunPython operation to populate the database, you also need to create code that reverses this operation.
An example from documentation:
from django.db import migrations
def forwards_func(apps, schema_editor):
# We get the model from the versioned app registry;
# if we directly import it, it'll be the wrong version
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).bulk_create([
Country(name="USA", code="us"),
Country(name="France", code="fr"),
])
def reverse_func(apps, schema_editor):
# forwards_func() creates two Country instances,
# so reverse_func() should delete them.
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).filter(name="USA", code="us").delete()
Country.objects.using(db_alias).filter(name="France", code="fr").delete()
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(forwards_func, reverse_func),
]
Basically, you need a reverse function, which in many cases can be simply:def reverse_func(apps, schema_editor):
pass
Django : How can I put the initial data into database by editting migrations file?
This will help https://docs.djangoproject.com/en/2.2/topics/migrations/#data-migrations
This is also the nice blog where you can create data migration similar to how you create database migration.
https://simpleisbetterthancomplex.com/tutorial/2017/09/26/how-to-create-django-data-migrations.html
Run migrations without loading initial_data.json
Consider upgrade to Django==1.8. You shouldn't have many problems after upgrade. What's your Django version?
Anyway, take a look at the documentation, since Django>=1.7 automatic loading of fixtures doesn't work:
An application uses migrations when you have the migrations folder with the __init__.py file inside it.If an application uses migrations, there is no automatic loading of fixtures
If you use Django>=1.7 and you use migrations in your app, you don't have automatic fixtures loading when you run python manage.py migrate
.
But, if you don't use migrations in your app, you always have automatic fixtures loading if your fixture file is named initial_data.json.
You can rename the initial_data.json file to any other name (like mydata.json) in order to avoid automatic fixtures loading, then, you can load the data any time you want by running:
django-admin.py loaddata mydata.json
Django 1.10 - how to load initial users
You can create fixture from default user model by below command:
python manage.py dumpdata auth.user -o FIXTURE_ADDRESS
and load initial data by below command:python manage.py loaddata FIXTURENAME
that FIXTURENAME
is name of your fixture in one of FIXTURE_DIRS
.The
FIXTURE_DIRS
by default is fixtures. Initial dynamic data for django database
I found a nice solution. I combined the following very nice python packages FactoryBoy + django-dynamic-fixtures + Faker. Works fine for me. I hope it will hep someone
Related Topics
Does Conda Replace the Need for Virtualenv
How to Write Utf-8 in a CSV File
Python MySQL Connector - Unread Result Found When Using Fetchone
Possible Values from Sys.Platform
Global Dictionaries Don't Need Keyword Global to Modify Them
Python Observer Pattern: Examples, Tips
How to Access Class Member Variables in Python
Numpy 1.21.2 May Not Yet Support Python 3.10
Pandas Groupby and Sum Only One Column
Numpy Argsort - What Is It Doing
How Does Sklearn.Svm.Svc's Function Predict_Proba() Work Internally
How to Convert Datetime.Timedelta to Minutes, Hours in Python
Create a Custom Transformer in Pyspark Ml