How to define default data for Django Models?
Asked Answered
J

5

35

I want my application to have default data such as user types.

What's the most efficient way to manage default data after migrations?

It needs to handle situations such as, after I add a new table, it adds the default data for it.

Johannajohannah answered 28/9, 2016 at 6:21 Comment(0)
F
16

Update:

most users are looking for data migration as suggested by @durdenk in https://mcmap.net/q/423228/-how-to-define-default-data-for-django-models. But what OP was asking is about a way to add data after migrations, that is why this is accepted answer.

Original answer:

I think what you are looking for is fixtures https://docs.djangoproject.com/en/1.10/howto/initial-data/

From docs

It’s sometimes useful to pre-populate your database with hard-coded data when you’re first setting up an app. You can provide initial data via fixtures.

Also read this https://code.djangoproject.com/wiki/Fixtures

Freya answered 28/9, 2016 at 6:25 Comment(4)
The docs contradict this answer: "If you want to automatically load initial data for an app, don’t use fixtures. Instead, create a migration for your application with RunPython or RunSQL operations."Welty
@Welty OP asked for "Whats the most efficient way to manage default data after migrations." And even though there was answer about migrations he selected my answer as correct one for his question.Freya
@Welty also the quote you've used from docs is about app not about project.Freya
The whole idea of fixtures, to my understanding, is to prepare sample data mainly for tests. That has nothing to do with defining some permanent default/system/special records for a new table, like OP asked.Slavism
H
65

You need to create an empty migration file and Do your stuff in operations block, as explained in docs.

Data Migrations

As well as changing the database schema, you can also use migrations to change the data in the database itself, in conjunction with the schema if you want.

Now, all you need to do is create a new function and have RunPython use it

Docs explains this with an example to show ,how to communicate with your models.

From Docs

To create an empty migration file,

python manage.py makemigrations --empty yourappname

And this is the example how to update a newly added field.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

def combine_names(apps, schema_editor):
    # We can't import the Person model directly as it may be a newer
    # version than this migration expects. We use the historical version.
    Person = apps.get_model("yourappname", "Person")
    for person in Person.objects.all():
        person.name = "%s %s" % (person.first_name, person.last_name)
        person.save()

class Migration(migrations.Migration):
    initial = True

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

    operations = [
        migrations.RunPython(combine_names),
    ]
Headstrong answered 28/9, 2016 at 9:10 Comment(6)
worked great, but seems like needed to load the whole Person table into the memory... isn't there a better way to iterate over all the Person objects?Duggan
Django's way is to use iterators, Person.objects.all().iterator() ? Haven't tested.Headstrong
Can this be done in the same migration as 0001, after the table gets created? e.g. operations = [migrations.CreateModel(...), migrations.RunPython(...)]Megathere
Yes, operations is a list and you can modify django-created migration files and add your own functionality.Headstrong
@Headstrong how do you commit this file? Django generally ignores the migration generated files so asking. Do you mention the file in .gitignore to ignore for ignoring?Conceited
@BhaskarDabhi , django has nothing to do with git. Make sure not to include these files in your gitignore and commit migration files. Migration files are a part of your application.Headstrong
A
35

The accepted answer is fine. But, since OP asked the question in the context of adding new rows and not updating existing entries. Here is the code snippet for adding new entries :

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('loginmodule', '0002_login_avatar'),
    ]

    def insertData(apps, schema_editor):
     Login = apps.get_model('loginmodule', 'Login')
     user = Login(name = "admin", login_id = "admin", password = "password", email = "[email protected]", type = "Admin", avatar="admin.jpg")
     user.save()


    operations = [
        migrations.RunPython(insertData),
    ]
Aromaticity answered 5/2, 2019 at 10:7 Comment(0)
F
16

Update:

most users are looking for data migration as suggested by @durdenk in https://mcmap.net/q/423228/-how-to-define-default-data-for-django-models. But what OP was asking is about a way to add data after migrations, that is why this is accepted answer.

Original answer:

I think what you are looking for is fixtures https://docs.djangoproject.com/en/1.10/howto/initial-data/

From docs

It’s sometimes useful to pre-populate your database with hard-coded data when you’re first setting up an app. You can provide initial data via fixtures.

Also read this https://code.djangoproject.com/wiki/Fixtures

Freya answered 28/9, 2016 at 6:25 Comment(4)
The docs contradict this answer: "If you want to automatically load initial data for an app, don’t use fixtures. Instead, create a migration for your application with RunPython or RunSQL operations."Welty
@Welty OP asked for "Whats the most efficient way to manage default data after migrations." And even though there was answer about migrations he selected my answer as correct one for his question.Freya
@Welty also the quote you've used from docs is about app not about project.Freya
The whole idea of fixtures, to my understanding, is to prepare sample data mainly for tests. That has nothing to do with defining some permanent default/system/special records for a new table, like OP asked.Slavism
D
1

Steps are very simple consider you have and app called api

Step # 1 make sure you have default migration already ran atleast one

python3 manage.py makemigrations
python3 manage.py migrate 

Now next step is to create empty migration file in your app for this execute below command

python manage.py makemigrations inventory --empty --name populate_initial_data

above command will generate an empty migration this is the file in which you can define you data this file can be find under migrations directory in my case its in api/migrations/0038_populate_initial_data.py.

next step is to add data in migration file i am adding data as per my database model i define as

from django.db import migrations
def create_initial_data(apps, schema_editor):
    AWSResourceType = apps.get_model('api', 'aws_resources_types')

    
    
    # Insert EC2Instance data
    AWSResourceType.objects.create(
        aws_resource_name='ec2',
        aws_resource_type='compute'
    )
    AWSResourceType.objects.create(
        aws_resource_name='s3',
        aws_resource_type='storage'
    )
    AWSResourceType.objects.create(
        aws_resource_name='rds',
        aws_resource_type='compute'
    )
    AWSResourceType.objects.create(
        aws_resource_name='cloudfront',
        aws_resource_type='cdn'
    )
    AWSResourceType.objects.create(
        aws_resource_name='vpc',
        aws_resource_type='networking'
    )
    AWSResourceType.objects.create(
        aws_resource_name='elastic_ip',
        aws_resource_type='networking'
    )  

class Migration(migrations.Migration):

    dependencies = [
        ('api', '0037_merge_20240715_1331'),
    ]

    operations = [
        migrations.RunPython(create_initial_data),
    ]

Now in last run the migrations.

python3 manage.py migrate 

In my case output looks like below

(.backend) (base) mansoor.hasan@PURE-DEV-MANSOORHASAN panther-backend % python manage.py migrate
Operations to perform:
  Apply all migrations: admin, api, auth, contenttypes, django_celery_beat, sessions
Running migrations:
  Applying api.0038_populate_initial_data... OK
Depository answered 15/7, 2024 at 13:43 Comment(0)
P
-5

Answer is given above just to show how to insert new rows to the table.

from django.db import migrations, models
from yourapp.models import <yourmodel>

def combine_names(apps, schema_editor):
    obj = <yourmodel>(arrib=value)
    obj.save()

For example let's say you have model Person

person = Person(first_name='raj', last_name='shah')
person.save()
Pentagrid answered 13/9, 2018 at 17:36 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.