Working with Django ORM migrations

Valerio Barbera

One of the key features of Django’s ORM is its migration system, which automates the process of database schema changes over time. In this tutorial, we will dive deep into understanding how Django ORM migrations work and how you can effectively use them in your projects.

As mentioned in previous articles, our machine learning APIs are built on top of Django, the most used framework to build REST applications in Python. And we use Django ORM to interact and maintain the SQL database.

This series of articles represents the knowledge we are building internally working with Django.

Overview of Django ORM Migrations

Django migrations allow developers to create, manage, and apply database schema changes over time, making it easier to evolve your database schema alongside your application. Migrations are written in Python and are stored as files in your Django project. They provide a version control-like system for database schemas.

Setting Up Migrations

To use ORM migrations in Django, you need to make sure that the django.contrib.migrations app is included in your project’s settings file (settings.py). This app is responsible for handling database migrations.

Creating Database Models

In Django, database models are defined as Python classes using Django’s django.db.models module. Each model class represents a database table, and the attributes of the class define the fields of the table. When creating or modifying models, Django’s migration system keeps track of the changes and generates corresponding migration files.

Here’s an example of a simple Django model representing a blog post:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

Generating Migrations

Once you have defined your database models, you need to create migrations for them. Django provides a command-line utility called makemigrations that automatically creates migration files based on the changes you made to your models.

To generate migrations, run the following command in your terminal:

python manage.py makemigrations

Django will scan your models and generate a migration file (a Python file) for each database schema change.

Applying Migrations

After generating the migrations, you need to apply them to your database to make the corresponding schema changes. Django provides the migrate command to apply migrations.

To apply migrations, run the following command:

python manage.py migrate

Django will execute the migrations in the order they were created, updating your database schema accordingly.

Handling Database Schema Changes

As your project evolves, you might need to make changes to your existing models or add new models. Django’s migration system provides various operations to handle schema changes, such as adding fields, modifying fields, deleting fields, creating tables, and more.

Here are a few examples of common migration operations.

Adding a new field to an existing model

from django.db import migrations, models

class Migration(migrations.Migration):

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

    operations = [
        migrations.AddField(
            model_name='mymodel',
            name='new_field',
            field=models.CharField(max_length=50),
        ),
    ]

Modifying an existing field

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0002_previous_migration'),
    ]

    operations = [
        migrations.AlterField(
            model_name='mymodel',
            name='existing_field',
            field=models.IntegerField(),
        ),
    ]

Deleting a field

from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0003_previous_migration'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='mymodel',
            name='obsolete_field',
        ),
    ]

Advanced Migration Operations

Django ORM migrations also support more advanced operations, such as data migrations, running custom SQL, creating indexes, and more. These operations can be used to perform complex database schema changes.

For example, here’s a data migration that populates a newly added field with some initial values:

from django.db import migrations

def populate_new_field(apps, schema_editor):
    MyModel = apps.get_model('myapp', 'MyModel')
    for instance in MyModel.objects.all():
        instance.new_field = 'default value'
        instance.save()

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0004_auto_20230101_1234'),
    ]

    operations = [
        migrations.RunPython(populate_new_field),
    ]

Rolling Back Migrations

Django provides a way to reverse previously applied migrations using the migrate command with the –fake or –fake-initial option. This allows you to roll back migrations in case of errors or when you need to revert to a previous state.

For example, to rollback the last applied migration, use the following command:

python manage.py migrate myapp 0003_previous_migration --fake

Migrations in Production

When deploying your Django application to production, it is crucial to have a solid migration strategy. It’s recommended to apply migrations as part of your deployment process to ensure your database schema is always up to date.

You can automate the migration process by running the migrate command during deployment or using tools like Django’s migrate management command in combination with deployment tools like Ansible, Fabric, or Docker.

New to Inspector? Try it for free now

Are you responsible for application development in your company? Consider trying my product Inspector to find out bugs and bottlenecks in your Django applucations automatically. Before your customers stumble onto the problem.

Inspector is usable by any IT leader who doesn’t need anything complicated. If you want effective automation, deep insights, and the ability to forward alerts and notifications into your preferred messaging environment try Inspector for free. Register your account.

Or learn more on the website: https://inspector.dev

Related Posts

Neuron AI Laravel SDK

For a long time, the conversation around “agentic AI” seemed to happen in a language that wasn’t ours. If you wanted to build autonomous agents, the industry nudge was often to step away from the PHP ecosystem and move toward Python. But for those of us who have built our careers, companies, and products on

PHP’s Next Chapter: From Web Framework to Agent Framework

I’ve spent the last year building Neuron, a PHP framework designed specifically for agentic AI applications. What started as a technical challenge became something else entirely when developers began reaching out with stories I wasn’t prepared to hear. They weren’t asking about framework features or deployment strategies. They were telling me about losing their jobs.

Storing LLM Context the Laravel Way: EloquentChatHistory in Neuron AI

I’ve spent the last few weeks working on one of the most important components of Neuron the Chat History. Most solutions treat conversation history in AI Agents forcing you to build everything from scratch. When I saw Laravel developers adopting Neuron AI, I realized they deserved better than that. The current implementation of the ChatHisotry