Django ORM

Django ORM is the Active Record style ORM of the Django framework. It features model-driven database design, automatic migrations, and deep integration with the admin interface, supporting PostgreSQL, MySQL, SQLite, Oracle, and more.

ORMPythonDjangoActive RecordWeb Development

GitHub Overview

django/django

The Web framework for perfectionists with deadlines.

Stars84,248
Watchers2,284
Forks32,718
Created:April 28, 2012
Language:Python
License:BSD 3-Clause "New" or "Revised" License

Topics

appsdjangoframeworkmodelsormpythontemplatesviewsweb

Star History

django/django Star History
Data as of: 7/17/2025, 10:32 AM

Library

Django ORM

Overview

Django ORM is the Active Record style ORM of the Django framework. It features model-driven database design, automatic migrations, and deep integration with the admin interface, supporting PostgreSQL, MySQL, SQLite, Oracle, and more.

Details

Django ORM is designed based on the Convention over Configuration philosophy, enabling powerful database operations with minimal configuration. It automatically generates database tables from models defined as Python classes and provides an intuitive query API. Integration with Django's admin interface makes CRUD operations easily executable.

Key Features

  • Active Record Pattern: Integrates business logic and data access in model classes
  • Automatic Migrations: Automatically generates migration files from model changes
  • Admin Interface: Automatic CRUD screen generation for models
  • Rich Field Types: Supports diverse data types
  • Powerful QuerySet API: Efficient query execution through lazy evaluation

Pros and Cons

Pros

  • Low learning curve with beginner-friendly design
  • Overwhelming development productivity through Django admin interface
  • Natural and readable API for Python developers
  • Rich documentation and community support
  • Optimal for CRUD-centered web application development

Cons

  • Limited expression for complex queries in some cases
  • Difficult to use with other frameworks due to Django framework dependency
  • Complex performance tuning in large-scale systems
  • Direct control of raw SQL difficult due to ORM abstraction

Reference Pages

Code Examples

Installation and Basic Setup

pip install Django
django-admin startproject myproject
cd myproject
python manage.py startapp myapp
# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'myuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',  # Add your application
]

Basic CRUD Operations (Model Definition, Create, Read, Update, Delete)

# models.py
from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['-created_at']

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField(blank=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-created_at']

# Run migrations
# python manage.py makemigrations
# python manage.py migrate

# Basic CRUD operations
from myapp.models import User, Post

# Create
user = User.objects.create(
    name='John Doe',
    email='[email protected]'
)

# Read
all_users = User.objects.all()
user_by_email = User.objects.get(email='[email protected]')
filtered_users = User.objects.filter(name__icontains='John')

# Update
user = User.objects.get(id=1)
user.name = 'John Smith'
user.save()

# Bulk update
User.objects.filter(name__icontains='John').update(name='Updated')

# Delete
user = User.objects.get(id=1)
user.delete()

# Bulk delete
User.objects.filter(name='Test').delete()

Advanced Queries and Relationships

from django.db.models import Q, Count, Avg, Max, Min
from datetime import datetime, timedelta

# Complex conditional queries
recent_users = User.objects.filter(
    Q(created_at__gte=datetime.now() - timedelta(days=30)) &
    Q(email__endswith='@company.com')
).order_by('-created_at')[:10]

# JOIN queries (select_related)
posts_with_author = Post.objects.select_related('author').all()

# Reverse reference queries (prefetch_related)
users_with_posts = User.objects.prefetch_related('posts').all()

# Aggregation queries
user_stats = User.objects.aggregate(
    total_users=Count('id'),
    avg_posts=Avg('posts__id'),
    latest_user=Max('created_at')
)

# Grouping queries
post_counts = User.objects.annotate(
    post_count=Count('posts')
).filter(post_count__gt=5)

# Subqueries
active_users = User.objects.filter(
    id__in=Post.objects.values_list('author_id', flat=True).distinct()
)

# Complex QuerySet operations
complex_query = Post.objects.select_related('author').filter(
    author__email__endswith='@company.com',
    created_at__gte=datetime.now() - timedelta(days=7)
).annotate(
    author_post_count=Count('author__posts')
).order_by('-created_at', 'title')

# Raw SQL queries
users = User.objects.raw(
    "SELECT * FROM myapp_user WHERE email LIKE %s",
    ['%@company.com']
)

Migrations and Schema Management

# Generate migration files
python manage.py makemigrations

# Specific app migrations
python manage.py makemigrations myapp

# Execute migrations
python manage.py migrate

# Check migration status
python manage.py showmigrations

# View migration SQL
python manage.py sqlmigrate myapp 0001
# Custom migration
# migrations/0002_custom_migration.py
from django.db import migrations

def forwards_func(apps, schema_editor):
    User = apps.get_model('myapp', 'User')
    db_alias = schema_editor.connection.alias
    User.objects.using(db_alias).filter(
        name='old_name'
    ).update(name='new_name')

def reverse_func(apps, schema_editor):
    User = apps.get_model('myapp', 'User')
    db_alias = schema_editor.connection.alias
    User.objects.using(db_alias).filter(
        name='new_name'
    ).update(name='old_name')

class Migration(migrations.Migration):
    dependencies = [
        ('myapp', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(forwards_func, reverse_func),
    ]

Performance Optimization and Advanced Features

from django.db import transaction
from django.core.cache import cache

# Transaction management
@transaction.atomic
def create_user_with_posts():
    user = User.objects.create(
        name='Jane Doe',
        email='[email protected]'
    )
    
    Post.objects.create(
        title='First Post',
        content='My first post using Django ORM',
        author=user
    )
    
    return user

# Batch operations
users_data = [
    User(name='User 1', email='[email protected]'),
    User(name='User 2', email='[email protected]'),
    User(name='User 3', email='[email protected]'),
]
User.objects.bulk_create(users_data)

# Batch update
User.objects.bulk_update(
    users_data,
    ['name', 'email']
)

# QuerySet optimization
# Avoiding N+1 problem
efficient_query = Post.objects.select_related('author').prefetch_related(
    'author__posts'
).all()

# Index hints
from django.db.models import Index

class User(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    
    class Meta:
        indexes = [
            Index(fields=['name', 'email']),
            Index(fields=['-created_at']),
        ]

# Custom manager
class PublishedPostManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(is_published=True)

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    is_published = models.BooleanField(default=False)
    
    objects = models.Manager()  # Default manager
    published = PublishedPostManager()  # Custom manager

# Usage example
published_posts = Post.published.all()

Framework Integration and Practical Examples

# Django REST Framework integration
from rest_framework import serializers, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

class UserSerializer(serializers.ModelSerializer):
    post_count = serializers.SerializerMethodField()
    
    class Meta:
        model = User
        fields = ['id', 'name', 'email', 'created_at', 'post_count']
    
    def get_post_count(self, obj):
        return obj.posts.count()

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
    @action(detail=True, methods=['get'])
    def posts(self, request, pk=None):
        user = self.get_object()
        posts = user.posts.all()
        return Response([{
            'id': post.id,
            'title': post.title,
            'created_at': post.created_at
        } for post in posts])

# Celery task integration
from celery import shared_task

@shared_task
def process_user_data(user_id):
    try:
        user = User.objects.get(id=user_id)
        # Execute heavy processing in background
        user.processed = True
        user.save()
        return f"User {user.name} processed successfully"
    except User.DoesNotExist:
        return f"User with id {user_id} not found"

# Django admin interface
from django.contrib import admin

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    list_display = ['name', 'email', 'created_at', 'post_count']
    list_filter = ['created_at']
    search_fields = ['name', 'email']
    readonly_fields = ['created_at', 'updated_at']
    
    def post_count(self, obj):
        return obj.posts.count()
    post_count.short_description = 'Post Count'

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ['title', 'author', 'created_at']
    list_filter = ['created_at', 'author']
    search_fields = ['title', 'content']
    autocomplete_fields = ['author']