Overview

Django 3.0, released on December 2, 2019, opens a new era for the framework with the arrival of ASGI (Asynchronous Server Gateway Interface) support. Until now, Django only supported WSGI, a synchronous protocol. ASGI enables leveraging asynchronous programming for WebSockets, streaming, and long-lived connections. This release also adds official MariaDB support and enumeration-based choices.

Key Features

ASGI support

Django 3.0 generates an asgi.py file in new projects, alongside the traditional wsgi.py. This ASGI entry point allows deploying the application with asynchronous servers like Daphne or Uvicorn. For now, views remain synchronous; native async view support will arrive in Django 3.1.

python
# my_project/asgi.py (auto-generated)
import os
from django.core.asgi import get_asgi_application

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

# Deploy with Uvicorn
# pip install uvicorn
# uvicorn my_project.asgi:application --host 0.0.0.0 --port 8000

# Deploy with Daphne
# pip install daphne
# daphne my_project.asgi:application --bind 0.0.0.0 --port 8000

MariaDB support

MariaDB is now officially supported as a database backend. While the MySQL backend already worked with MariaDB in most cases, official support guarantees automated testing and dedicated documentation.

python
# settings.py: MariaDB configuration
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'my_application',
        'USER': 'django_user',
        'PASSWORD': 'secret',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': {
            'charset': 'utf8mb4',
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}

# Check MariaDB version
from django.db import connection

with connection.cursor() as cursor:
    cursor.execute('SELECT VERSION()')
    version = cursor.fetchone()[0]
    print(f"MariaDB version: {version}")
    # MariaDB version: 10.4.12-MariaDB

Enumeration-based choices

The TextChoices and IntegerChoices classes offer a readable, type-safe way to define model field choices. They replace the tuples of constants used previously.

python
from django.db import models

class Ticket(models.Model):
    class Status(models.TextChoices):
        OPEN = 'OP', 'Open'
        IN_PROGRESS = 'IP', 'In Progress'
        RESOLVED = 'RE', 'Resolved'
        CLOSED = 'CL', 'Closed'

    class Priority(models.IntegerChoices):
        LOW = 1, 'Low'
        NORMAL = 2, 'Normal'
        HIGH = 3, 'High'
        CRITICAL = 4, 'Critical'

    title = models.CharField(max_length=200)
    status = models.CharField(
        max_length=2,
        choices=Status.choices,
        default=Status.OPEN,
    )
    priority = models.IntegerField(
        choices=Priority.choices,
        default=Priority.NORMAL,
    )

# Usage
ticket = Ticket(title='Homepage bug', priority=Ticket.Priority.HIGH)
print(ticket.get_status_display())    # Open
print(ticket.get_priority_display())   # High

# Filtering
urgent = Ticket.objects.filter(
    priority__gte=Ticket.Priority.HIGH,
    status=Ticket.Status.OPEN,
)

Sources