Django 3.2 LTS: Why You Should Upgrade

python django

Django 3.2 LTS is here. With support until April 2024, it’s the stable foundation for the next three years. Here’s what’s new and why you should upgrade.

LTS Explained

VersionReleaseEnd Support
Django 2.2 LTSApr 2019Apr 2022
Django 3.2 LTSApr 2021Apr 2024
Django 4.2 LTSApr 2023Apr 2026

LTS releases get security updates for 3 years. Non-LTS releases only get 16 months.

New Features

Functional Indexes

Create indexes on expressions:

from django.db import models
from django.db.models.functions import Lower

class Article(models.Model):
    title = models.CharField(max_length=200)
    
    class Meta:
        indexes = [
            models.Index(Lower('title'), name='lower_title_idx'),
        ]

Useful for case-insensitive queries:

# This query can now use the index
Article.objects.filter(title__iexact='django guide')

Covering Indexes (PostgreSQL)

Include additional columns in indexes:

class Article(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    created_at = models.DateTimeField()
    
    class Meta:
        indexes = [
            models.Index(
                fields=['author'],
                include=['title', 'created_at'],
                name='author_covering_idx',
            ),
        ]

The index includes title and created_at, enabling index-only scans:

# May avoid table access entirely
Article.objects.filter(author=user).values('title', 'created_at')

JSONField for All Databases

JSONField now works on all databases, not just PostgreSQL:

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    preferences = models.JSONField(default=dict)

# Usage
profile.preferences = {
    'theme': 'dark',
    'notifications': True,
    'sidebar_collapsed': False
}
profile.save()

# Query
Profile.objects.filter(preferences__theme='dark')

SQLite, MySQL, and MariaDB now supported.

AppConfig.default_auto_field

Control default primary key type:

# settings.py
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Or per-app:

# myapp/apps.py
class MyAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'myapp'

New projects default to BigAutoField. Existing projects should migrate carefully.

Admin Site Improvements

Native dark mode support:

# Django detects system preference
# Or override in templates

Other admin improvements:

Collation Support

Database collation on CharField:

class Name(models.Model):
    name = models.CharField(
        max_length=100,
        db_collation='en_US.utf8'
    )

Useful for locale-specific sorting.

Simplified URL Patterns

Optional capturing groups:

# Before
path('articles/', views.list),
path('articles/<int:year>/', views.list),

# After (Django 3.2+)
re_path(r'^articles/(?:(?P<year>\d{4})/)?$', views.list),

Performance Improvements

Optimized ORM

Query generation is faster:

Cached Template Loader Default

In production, templates are cached by default:

# DEBUG = False automatically enables caching

Deprecations

url() is Gone

Use path() or re_path():

# Old (removed in Django 4.0)
from django.conf.urls import url
url(r'^articles/$', views.list)

# New
from django.urls import path, re_path
path('articles/', views.list)
re_path(r'^articles/(?P<slug>[\w-]+)/$', views.detail)

Upgrade Guide

Step 1: Check Compatibility

python -Wd manage.py test

Review deprecation warnings.

Step 2: Update Dependencies

pip install Django==3.2
pip install --upgrade psycopg2 celery djangorestframework

Check all packages support Django 3.2.

Step 3: Run Migrations

python manage.py migrate

Step 4: Handle Auto Field Warnings

You’ll see warnings about DEFAULT_AUTO_FIELD:

# Add to settings.py to maintain current behavior
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

# Or for new projects, use BigAutoField
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Step 5: Test Thoroughly

python manage.py test

Step 6: Update url() to path()

# Search for url( and replace with path( or re_path(

Should You Upgrade?

From Django 2.2 LTS

Yes. 2.2 support ends April 2022:

From Django 3.0/3.1

Yes. Non-LTS releases have shorter support:

From Older Versions

Upgrade path:

Django 1.11 → 2.2 → 3.2

Don’t skip LTS versions.

Final Thoughts

Django 3.2 LTS is the stable choice for production. Functional indexes, universal JSONField, and three years of support make it the foundation for serious projects.

Upgrade now. Your future self will thank you.


LTS: Long-Term Stability.

All posts