from django.db import models
from django.contrib.postgres.indexes import GinIndex
class Post(models.Model):
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(unique=True)
content = models.TextField()
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
status = models.CharField(max_length=20)
published_at = models.DateTimeField(null=True, blank=True, db_index=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
# Compound index for common query pattern
models.Index(fields=['status', 'published_at'], name='post_status_pub_idx'),
# Partial index for published posts only
models.Index(
fields=['published_at'],
condition=models.Q(status='published'),
name='published_posts_idx'
),
# GIN index for full-text search
GinIndex(fields=['title', 'content'], name='post_search_idx'),
]
ordering = ['-published_at']
Indexes dramatically improve query performance. I add indexes via Meta.indexes or db_index=True on frequently-filtered fields. Compound indexes help queries filtering on multiple fields. For text search, I use GinIndex on PostgreSQL. I index foreign keys automatically. The EXPLAIN query shows if indexes are used. Too many indexes slow down writes, so I profile first. For large tables, I create indexes concurrently in separate migrations. This prevents locking during deployment.