Set up and Load Initial Data in Django
Tags: django, python, webdev, beginners
Published: 2021-12-15 09:14:17

**Introduction**
Sometimes there's a need to have a set of initial data once we spin up our application. Reasons vary, but the need is there. Django provides two ways of setting up and loading this initial data to our database.
   * Using Fixtures
   * Using Migrations

For the purposes of this brief explanation, we will have a model, Book in our app called Main
```
# main/models.py

from django import models

class Book(models.Model):
    name = models.CharField(max_length=50)
    author = models.CharField(max_length=20)
```

## Using Fixtures
A fixture is a collection of data that Django knows how to import into a database. In this specific approach to fixtures, our data is not going to be loaded automatically. We are going to create the fixture by hand, then load them by running a command.

#### Creating Fixtures
First, we need a folder to hold our fixtures. We can create a folder called `fixtures` at app level (in our app Main), or we can have all our fixtures at project level by defining `FIXTURE_DIRS` in our `settings.py`. 
FIXTURE_DIRS should contain a list of directories where Django should look for fixtures.

In this case, I have set  FIXTURE_DIRS at project level to have it as:
```
# my_project/setting.py

FIXTURE_DIRS =  BASE_DIR / "fixtures" 

```
Create the directory `fixtures` at project level. Here, we are going to create our fixtures, which can be any of the following formats:
* JSON
* XML
* YAML

We are going to use JSON, so within our fixtures directory, let's create a file `books.json`. I prefer to name the fixtures after the app that their models belong to.

```
# fixtures/books.json

[
  {
    "model": "main.book",
    "pk": 1,
    "fields": {
      "name": "Atomic Habits",
      "author": "James Clear",
    }
  },
  {
    "model": "main.book",
    "pk": 2,
    "fields": {
      "name": "Permanent Record",
      "author": "Edward Snowden",
    }
  }
]

```

#### Loading data
Since we have created our fixtures by hand, we need to call the individually to load the data:

python manage.py loaddata fixture_file_name

`python manage.py loaddata books.json`


## Using Migrations
In this method, we are going to generate our own empty migration by running a command of the similar form/syntax as shown:

`python manage.py makemigrations --empty app_name`

As previously mentioned, our app name is Main, and our model is Book, so our command should be:

`python manage.py makemigrations --empty main`

This command will generate an automatically migration file, within your app's migrations folder. The file should be of a similiar format to this:

```
# Generated by Django 3.0.11 on 2021-12-15 08:35
from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
        ('main', '0001_initial'),
    ]

    operations = [
    ]

```

#### Create Function to add data
We need to create a function that will add the data. This function must have two arguments, which are:
* *App Registry* - A registry of all your apps, including 
historical versions of their models.

* *Schema Editor* - This is what is used to manually 
effect database schema changes, (enforce changes to database)


With this is in mind, let's write our function:

```
def load_initial_data(apps, schema_editor):
    # get our model
    # get_model(appname, modelname)
    book_model = apps.get_model('main', 'Book')
    book_model.objects.create (
        name = "Atomic Habits", author = "James Clear"
        )
    book_model.objects.create (
        name = "Permanent Record", author = "Edward Snowden"
        )

```

This function should be within your migration file, as follows:

```
# Generated by Django 3.0.11 on 2021-12-15 08:35
from django.db import migrations

def load_initial_data(apps, schema_editor):
    # get our model
    # get_model(appname, modelname)
    book_model = apps.get_model('main', 'Book')
    book_model.objects.create (
        name = "Atomic Habits", author = "James Clear"
        )
    book_model.objects.create (
        name = "Permanent Record", author = "Edward Snowden"
        )

class Migration(migrations.Migration):

    dependencies = [
        ('main', '0001_initial'),
    ]

    operations = [
    ]

```

We can now add our `load_initial_data` function to the `operations` list in our migration file:

```
operations = [
   migrations.RunPython(load_initial_data),
]
```

Your complete migrations file should be similar to this:

```
# Generated by Django 3.0.11 on 2021-12-15 08:35
from django.db import migrations

def load_initial_data(apps, schema_editor):
    # get our model
    # get_model(appname, modelname)
    book_model = apps.get_model('main', 'Book')
    book_model.objects.create (
        name = "Atomic Habits", author = "James Clear"
        )
    book_model.objects.create (
        name = "Permanent Record", author = "Edward Snowden"
        )

class Migration(migrations.Migration):

    dependencies = [
        ('main', '0001_initial'),
    ]

    operations = [
       migrations.RunPython(load_initial_data),
    ]

```
#### Load data
Since our data is in a migration file, we need to migrate in order to load it. So, we simply run:

`python manage.py migrate`