Search code examples
pythondjangodjango-modelsdjango-migrations

How to add default data to django model


I have a web app with the following model

class Records(models.Model):
    alias = models.CharField(max_length=17, unique=True)
    status = models.BooleanField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    def __str__(self):
        return self.alias

    def list_data(self):
        return [self.alias, self.status, self.created_at, self.updated_at]

I want some default data to be populated into this model on creation. I went through the documentation and this StackOverflow question for doing the same.

I first ran this command to create a migrations file (0001_initial.py)

python manage.py makemigrations --empty main_app

I then edited the migrations file as follows

0001_initial.py

# Generated by Django 4.0.3 on 2022-04-23 05:57

from django.db import migrations

def add_initial_data(apps, schema_editor):

    Records = apps.get_model('main_app', 'Records')
    for record in Records.objects.all():
        record.alias = f'ACCORD1'
        record.status = True
        record.save()
        
        for i in range(2,6):
            record.alias = f'ACCORD{i}'
            record.status = False
            record.save()

class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.RunPython(add_initial_data)
    ]

When I run the migrations with the following command

python manage.py migrate

I get the following error

LookupError: No installed app with label 'main_app'.

I tried adding the dependency to the migrations file as follows

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

But this gives me the following error

django.db.migrations.exceptions.CircularDependencyError: main_app.0001_initial

I am not sure what I am doing wrong.


Solution

  • CircularDependencyError

    The circular dependency error is encountered when a file being called is associated with a dependency, which has the file being called as its dependency.

    In the file main_app/001_initial.py, you added the dependency main_app/001_initial.py by adding the line:

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

    On migration, the confusion arises whether to import the file main_app/001_initial.py or the dependency main_app/001_initial.py whose dependency is the file main_app/001_initial.py. Hence, creating a circular dependency pattern.

    Adding default values.

    Adding multiple rows of data from migration file is not part of a good coding paradigm. You would want to use a different method.

    Add default values to model itself.

    These values will only help to add default values when saving one instance at a time.

    class Records(models.Model):
        alias = models.CharField(max_length=17, unique=True, default="ACCORD")
        status = models.BooleanField(default=True)
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)
        
        def __str__(self):
            return self.alias
    

    Now there are multiple ways to populate the table with data.

    1. Link the django app to the database with data rows already in place.
    2. Add a serializer function BulkCreate to add values in bulk.
    3. Use the command line shell manually to create model instances that would populate the database table. You can read about using python manage.py shell and python manage.py shellplus.
    4. Use a python script to add the data by creating model instances with the desired values.

    Another tip

    Instead of using a list_data function in models.py, using a django serializer would serve more functionality and is a better way to code.

    The idea is to keep models.py as clean as possible with only the attribute definitions there.