Django 3.0 Released: ASGI Support Arrives

python backend django async

Django 3.0 landed on December 2, 2019. The headline: native ASGI support. Python 2 is finally gone. The async future begins.

Breaking Changes

Python 2 Is Gone

Django 3.0 requires Python 3.6+. Python 3.8 recommended.

# Check your version
python --version

# Update if needed
pyenv install 3.8.0
pyenv local 3.8.0

If you have Python 2 code, you can’t skip to Django 3.0. Upgrade to Python 3 first, then Django.

MySQL 5.6+ Required

Older MySQL versions are no longer supported.

Other Deprecations Removed

Things deprecated in 2.0/2.1 are now gone:

ASGI Support

The main event. Django now speaks ASGI natively.

Creating the ASGI Application

# myproject/asgi.py
import os
from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_asgi_application()

Running with ASGI Servers

# Uvicorn
pip install uvicorn
uvicorn myproject.asgi:application

# Daphne
pip install daphne
daphne myproject.asgi:application

# Hypercorn
pip install hypercorn
hypercorn myproject.asgi:application

What Works in ASGI Mode

Everything that worked in WSGI still works. ASGI is backward compatible.

What’s new:

What Doesn’t Work Yet

Django 3.0 is the foundation, not the finish line.

New Features

MariaDB Support

Official MariaDB backend:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb',
        'OPTIONS': {
            'read_default_file': '/path/to/my.cnf',
        },
    }
}

Exclusion Constraints (PostgreSQL)

from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import DateTimeRangeField, RangeOperators

class Reservation(models.Model):
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    timespan = DateTimeRangeField()
    
    class Meta:
        constraints = [
            ExclusionConstraint(
                name='no_overlapping_reservations',
                expressions=[
                    ('room', RangeOperators.EQUAL),
                    ('timespan', RangeOperators.OVERLAPS),
                ],
            ),
        ]

Prevent overlapping time ranges at the database level.

Filter Expressions

New database functions for filtering:

from django.db.models import Value
from django.db.models.functions import Reverse, Length

# Reverse strings
Article.objects.annotate(reversed_title=Reverse('title'))

# More function expressions available

Enum Improvements

Better support for Python Enums:

from enum import Enum

class Status(Enum):
    DRAFT = 'draft'
    PUBLISHED = 'published'
    ARCHIVED = 'archived'

class Article(models.Model):
    status = models.CharField(
        max_length=20,
        choices=[(s.value, s.name) for s in Status],
        default=Status.DRAFT.value,
    )

Security Updates

Password Hashing

PBKDF2 iterations increased again. Existing passwords auto-upgrade on login.

SECURE_REFERRER_POLICY

New setting for the Referrer-Policy header:

SECURE_REFERRER_POLICY = 'same-origin'

Upgrade Path

From Django 2.2 LTS

Smoothest path:

  1. Ensure you’re on Python 3.6+
  2. Run with deprecation warnings: python -Wd manage.py test
  3. Fix deprecation warnings
  4. Upgrade Django
  5. Run tests

From Django 2.0/2.1

Same process, but more deprecations to address.

From Django 1.11 LTS

Larger jump:

  1. Upgrade to Python 3.6+
  2. Upgrade to Django 2.2 LTS first
  3. Fix all deprecations
  4. Then upgrade to 3.0

Using Channels with Django 3.0

Django Channels works with ASGI:

# asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import myapp.routing

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            myapp.routing.websocket_urlpatterns
        )
    ),
})

Should You Upgrade?

Upgrade if:

Wait if:

The Async Roadmap

Django’s async journey:

The goal is full async capability without breaking sync code.

Final Thoughts

Django 3.0 is a milestone—the first step into async Django. The foundation is laid.

For most projects, the upgrade is straightforward. Python 3 requirement finally cleans up years of compatibility shims.

Welcome to async Django. The future is being built.


The async journey begins.

All posts