Performance

  • Advanced techniques to optimize Django applications for speed and scalability.
  • Why Performance Matters in Django?

    • Improves response time for users

    • Reduces server load and database queries

    • Critical for scalable applications

    • Prevents slow page loads in production

    Query Optimization

    Understanding Queries in Django ORM

    • Every ORM operation translates into SQL query

    • Too many queries → slows down app (N+1 problem)

    • Efficient queries → faster response, lower DB load

    Tips for Query Optimization

    1. Use select_related for foreign keys

      • Fetch related objects in single query

select_related Example

models.py

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
 # views.py
books = Book.objects.select_related('author').all()
for book in books:
    print(book.title, book.author.name)
  • 2. Code Description

    • Fetches books and authors in one query

    • Avoids multiple DB hits

    Use prefetch_related for ManyToMany or reverse relationships

prefetch_related Example

 authors = Author.objects.prefetch_related('book_set').all()
for author in authors:
    for book in author.book_set.all():
        print(author.name, book.title)
  • 2. Code Description

    • Reduces extra queries when fetching related sets

    • Efficient for ManyToMany or reverse ForeignKey

Avoid unnecessary queries

 # Bad
for book in Book.objects.all():
    print(book.author.name)  # extra query per book

# Good
books = Book.objects.select_related('author').all()
for book in books:
    print(book.author.name)
  • Use only() and defer() to load specific fields

Load Specific Fields

 books = Book.objects.only('title')  # load only title, skip author
  • Reduces data fetched from DB

    ORM Efficiency

    Use Aggregations & Annotations

    • Use Django ORM functions to perform calculations in DB

    • Reduces Python-side processing

ORM Aggregation

from django.db.models import Count
authors = Author.objects.annotate(book_count=Count('book'))
for author in authors:
    print(author.name, author.book_count)
  •  Description

    • Counts books per author in DB, not Python

    • More efficient for large datasets

    Use values() and values_list() for lightweight queries

values Example

# Fetch only names of authors
names = Author.objects.values_list('name', flat=True)
  • Avoids fetching full model objects

Use Indexes for Heavy Queries

class Book(models.Model):
    title = models.CharField(max_length=100, db_index=True)
  • Indexes speed up filter queries


Cache Frequently Accessed Data

Use Django cache framework:

from django.core.cache import cache

books = cache.get('all_books')
if not books:
    books = list(Book.objects.all())
    cache.set('all_books', books, 60*5)  # cache 5 minutes
  • Reduces database hits for repeated queries
    Profiling Queries

Check Queries Executed

from django.db import connection

books = Book.objects.all()
print(connection.queries)
  • Useful to identify N+1 problems

    Use Django Debug Toolbar

    • Install: pip install django-debug-toolbar

    • Shows SQL queries per view

    • Highlights slow queries