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 ( 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 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 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 = [

Modifying an existing field

from django.db import migrations, models
class Migration(migrations.Migration):
    dependencies = [
        ('myapp', '0002_previous_migration'),
    operations = [

Deleting a field

from django.db import migrations
class Migration(migrations.Migration):
    dependencies = [
        ('myapp', '0003_previous_migration'),
    operations = [

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'
class Migration(migrations.Migration):
    dependencies = [
        ('myapp', '0004_auto_20230101_1234'),
    operations = [

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 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:

Related Posts


PHP Iterators for walking through data structures – FastTips

PHP Iterators are essential tools for efficiently traversing and manipulating data structures like arrays, objects, and more. They provide a clean and memory-efficient way to work with large datasets without loading the entire dataset into memory at once. In this tutorial, we will explore PHP iterators and how to use them for walking through various

Adoption of AWS Graviton ARM instances (and what results we’ve seen)

Working in software and cloud services you’ve probably already heard about the launch of new the Graviton machines based on custom ARM CPUs from AWS (Amazon Web Services).  In this article you can learn the fundamental differences between ARM and x86 architecture and the results we’ve achieved after the adoption of Graviton ARM machines in

Announcing increased data retention for monitoring data

Long story short: In the last 2 months of work we’ve achieved great results in cost optimization by refactoring both our infrastructure and code architecture, and we want to pass this value to you in the form of a longer data retention for your monitoring data. Thanks to these changes we are increasing our computational