Loading Initial Data with Django 1.7 and Data Migrations

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

  1. Create your empty migration:

    In Django 1.7:

    python manage.py makemigrations --empty <yourapp>

    In Django 1.8+, you can provide a name:

    python manage.py makemigrations --empty <yourapp> --name load_intial_data
  2. Edit your migration file <yourapp>/migrations/0002_auto_xxx.py

    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. 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)

    Useful if you want to use a custom directory.

    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')

    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).

  3. 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:

If an application uses migrations, there is no automatic loading of fixtures

An application uses migrations when you have the migrations folder with the __init__.py file inside it.

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



Leave a reply



Submit