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.
GitHub Overview
django/django
The Web framework for perfectionists with deadlines.
Topics
Star History
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']