Danny
Danny

Reputation: 510

Struggling to turn JSON data into Django model object instances

I'm trying to take a list of JSON objects, turn them into Python dicts, then populate the Concert model with an object for each of the Python dicts.

import json
from models import Concert
with open('output.json') as f:
    data = json.load(f)
for concert in data:
    Concert.objects.create(**concert)

I'm getting an error message I haven't seen before:

ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

Is this something that can be easily addressed? There is a foreign key in my model that corresponds to one of the key-value pairs in the JSON objects; is that relevant to this error?

Upvotes: 1

Views: 441

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477676

This is a common error, if you write an independent python file and execute it.

Defining a custom command

Although you can make sure the Django framework is properly loaded, usually the idea is that you define a custom command [doc].

So in your file structure, if app is the application where your Concert is located, you can construct directories and files (here listed in boldface):

someapp/
    management/
        __init__.py
        commands/
            __init__.py
            load_concerts.py
    __init__.py
    models.py
    views.py

Where the __init__.py files are empty. Then your load_concerts.py can look like:

from django.core.management.base import BaseCommand, CommandError
import json
from app.models import Concert

class Command(BaseCommand):
    help = 'Load JSON concert data'

    def add_arguments(self, parser):
        parser.add_argument('concert_file', type=str)

    def handle(self, *args, **options):
        with open(options['concert_file']) as f:
            data = json.load(f)
        for concert in data:
            Concert.objects.create(**concert)

You can the execute the command with:

$ manage.py load_concerts output.json --settings=my_settings

So just like you run the server (well you can see this as a builtin command), you can thus add specific commands).

By defining the filename as a parameter, we can easily load any .json file we want.

An independent Python program

You can define a loose Python file. In that case you need to load the settings, with:

from django.conf import settings
from projectroot import settings as projectsettings
settings.configure(projectsettings)

import django
django.setup()

import json
from app.models import Concert

with open('output.json') as f:
    data = json.load(f)
for concert in data:
    Concert.objects.create(**concert)

Then you can set the PYTHONPATH to the project root, and thus load the specific settings, but I think this will probably result in more pain that to define a command you can easily reuse.

Upvotes: 5

Related Questions