Automatically Load Django Fixture
Asked Answered
C

4

6

I'm running Django 1.7. My file tree for the project is as such:

/project/app/fixtures/initial_data.json
/project/app/settings.py

I know I can run the python manage.py loaddata app/fixtures/initial_data.json command that will work for populating my database but I want to load it automatically when python manage.py migrate is run. My settings include:

FIXTURE_DIRS = (
    os.path.join(BASE_DIR, '/app/fixtures/'),
)

But the fixture is not applied when migrate is run. What seems to be the problem?

Cosh answered 6/1, 2015 at 22:39 Comment(0)
R
10

I'm afraid not and this is not your problem, because this is deprecated since Django 1.7:

READ HERE

Automatically loading initial data fixtures¶

Deprecated since version 1.7: If an application uses migrations, there is no automatic loading of fixtures. Since migrations will be required for applications in Django 1.9, this behavior is considered deprecated. If you want to load initial data for an app, consider doing it in a data migration.

If you create a fixture named initial_data.[xml/yaml/json], that fixture will be loaded every time you run migrate. This is extremely convenient, but be careful: remember that the data will be refreshed every time you run migrate. So don’t use initial_data for data you’ll want to edit.

If you really want this to work, you can always customise your manage.py,

# import execute_from_command_line
    from django.core.management import execute_from_command_line

    # add these lines for loading data
    if len(sys.argv) == 2 and sys.argv[1] == 'migrate':
        execute_from_command_line(['manage.py', 'loaddata'])

    execute_from_command_line(sys.argv)

Hope this helps.

Rollick answered 6/1, 2015 at 23:0 Comment(2)
I will extend the answer. If you need to load specific fixture, than write: execute_from_command_line(['manage.py', "loaddata", "my_specific_fixture_name.json"])Quinton
@AlexeiMarinichenko, nice addon! It makes more sense to capture the extra argument and pass on to manage.py command :-)Rollick
E
1

you can always create a custom migration file that loads fixtures. thus they won't be refreshed every time you run some commands, check this example I want to populate countries, cities, etc.

# world/migrations/0002_fixtures.py

from django.core.management import call_command
from django.db import migrations


def forwards_func(apps, schema_editor):
    fixture_labels = ['geoname_currency.json', 'geoname_country.json',
                      'geoname_region.json', 'geoname_subregion.json']
    call_command('loaddata', *[
        'world/fixtures/{}'.format(fixture)
        for fixture in fixture_labels
    ])


def reverse_func(apps, schema_editor):
    models = [
        apps.get_model("world", model_name)
        for model_name in ['Subregion', 'Region', 'Currency', 'Country']
    ]
    for model in models:
        model.objects.all().delete()


class Migration(migrations.Migration):
    dependencies = [
        ('world', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(forwards_func, reverse_func)
    ]
Eggshaped answered 17/12, 2023 at 14:34 Comment(0)
S
0

Sadly not enough points to be able to comment! This post is quite old... (Django 1.7 - 1.9)
Changing Manage.py is still a valid option to go!

  • A reminder to change "migrate" to "makemigrations"

if len(sys.argv) == 2 and (sys.argv[1] == 'makemigrations'):

Plus, for the people who don't often read the comments, add your JSON file to the "execute_from_command_line" function.

execute_from_command_line(['manage.py', 'loaddata', 'YourFileName.json'])

This way by running python manage.py makemigrations it will automatically load your fixture data stated in that file given hard-coded.

Needless to mention, every time you run that command it will override any data modification made to the models in that fixture.

Swiss answered 4/12, 2020 at 16:34 Comment(0)
P
0

I found myself in a similar requirement. I needed to aggregate and load fixtures across all apps in my project with a single command.

python manage.py loaddata --all should have sufficed but for some weird reasons - FIXTURE_DIRS in my project settings wasn't getting read. Thus, I tweaked manage.py file.

...
from project.settings import FIXTURE_DIRS

def main():
    ...
     if len(sys.argv) > 1 and sys.argv[1] == "loaddata" and sys.argv[2] == "--all":
        for fixtures_folder in FIXTURE_DIRS:
            fixtures = [filename for filename in os.listdir(fixtures_folder) if filename.endswith(".json")]
            for fixture in fixtures:
                fixture_path = os.path.join(fixtures_folder, fixture)
                command = f"python manage.py loaddata {fixture_path}"
                os.system(command)
                print(f"{fixture_path} completed")
    else:
        execute_from_command_line(sys.argv)

python manage.py loaddata --all can be ran successfully after migrating necessary changes to the DB.

Ploughboy answered 10/10, 2023 at 6:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.