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.
# 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.
# 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.
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,
)
