Preparing for Django 5.0: What's Coming

django python

Django 5.0 is coming in December. Here’s what to expect and how to prepare.

Big Changes

Python 3.10+ Required

Django 5.0 drops Python 3.8 and 3.9:

# Minimum required
python --version
# Python 3.10.x or higher

If you’re still on 3.9, upgrade first.

Default Async WSGI

Async views work without ASGI:

# Works with traditional WSGI
async def my_async_view(request):
    data = await fetch_external_api()
    return JsonResponse(data)

No need to switch to ASGI for basic async views.

New Features

Facet Filters in Admin

Counts in filter sidebar:

class ArticleAdmin(admin.ModelAdmin):
    list_filter = ['status', 'category']
    show_facets = admin.ShowFacets.ALWAYS  # New

Shows: “Published (45) | Draft (12)” in filters.

Simplified Form Field Rendering

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField()
    email = forms.EmailField()

# In template:
{{ form.name }}  # Renders complete field with wrapper, label, errors

More control with less template code.

Field Groups

class MyForm(forms.Form):
    class Meta:
        field_groups = {
            'personal': ['first_name', 'last_name'],
            'contact': ['email', 'phone'],
        }

Render groups together easily.

Database-Computed Default Values

from django.db.models import F
from django.db.models.functions import Now

class Event(models.Model):
    created_at = models.DateTimeField(db_default=Now())
    sequence = models.IntegerField(db_default=F('id'))

The database generates defaults, not Python.

More Expression Support in Constraints

from django.db.models import Q, F

class Booking(models.Model):
    start_date = models.DateField()
    end_date = models.DateField()
    
    class Meta:
        constraints = [
            models.CheckConstraint(
                check=Q(end_date__gt=F('start_date')),
                name='valid_date_range',
            )
        ]

Deprecations

logout() Requires POST

# Old way (deprecated)
path('logout/', auth_views.LogoutView.as_view(), name='logout'),

# GET requests to logout will be CSRF-vulnerable

# You need:
<form method="post" action="{% url 'logout' %}">
    {% csrf_token %}
    <button type="submit">Logout</button>
</form>

Model.objects.get_by_natural_key()

If you use natural keys, check the migration path.

Removed Features

Pre-Upgrade Checklist

1. Check Python Version

python --version
# Need 3.10+

2. Run with Deprecation Warnings

python -W error::DeprecationWarning manage.py check
python -W error::DeprecationWarning manage.py test

3. Update Dependencies

pip list --outdated
# Check if your packages support Django 5.0

Common packages to check:

4. Check Your LOGOUT Implementation

# If you have GET-based logout, update to POST

5. Test Thoroughly

# Create a virtual environment for testing
python -m venv test_dj5
source test_dj5/bin/activate
pip install Django>=5.0rc1
pip install -r requirements.txt
./manage.py test

Migration Path

From Django 4.2 LTS

# Recommended path
Django 4.2 Django 5.0

# Upgrade pip
pip install --upgrade pip

# Install 5.0
pip install Django>=5.0

From Older Versions

Django 3.2 → 4.2 → 5.0
Django 4.0 → 4.2 → 5.0
Django 4.1 → 4.2 → 5.0

Don’t skip LTS versions.

New Settings

# settings.py

# For the new form rendering system
FORM_RENDERER = 'django.forms.renderers.DjangoDivFormRenderer'

# Async configuration (if needed)
AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = True  # Example

When to Upgrade

Wait If

Upgrade Soon If

Release Timeline

Dec 2023:  Django 5.0 release
Apr 2024:  Django 5.1 release
Dec 2024:  Django 5.2 (next LTS)
Apr 2026:  Django 5.0 end of support

5.0 is not an LTS. Plan for 5.2 if you need long-term support.

Final Thoughts

Django 5.0 is a solid release without breaking changes for most projects. The admin improvements and form rendering updates are immediately useful.

Check your Python version, test with deprecation warnings, and you’ll likely upgrade smoothly.


Prepare now, upgrade smoothly.

All posts