What's New in Django 3.1?

Django 3.1 will be released in early August 2020 and comes with a number of major new features and many minor improvements including asynchronous views and middleware support, asynchronous tests, JSONField for all supported database backends (not just PostgreSQL), an updated admin page, SECURE_REFERRER_POLICY, and much more. The official release notes are the canonical reference, but this post will cover some of the highlights as well as tips for upgrading.

How to Upgrade

You really should strive to be on the latest version of both Django and Python. This will result in faster, more supported, and feature-laden code. To upgrade, create a new virtual environment, install Django 3.1, and run your test suite (you have one, yes?) by adding the -Wa flag to show full deprecation warnings.

(env) $ python -Wa manage.py test

If you don't have tests in your project yet, you can still use python -Wa manage.py runserver to see some warnings. Refer to the official upgrade list for more advice.

Django 3.1 requires Python 3.6, 3.7, or 3.8. You can read more about supported Python versions on the Django prerequisites page. If you're curious about Django's version and release policy, the download page shows the supported versions timeline and future LTS (long-term support) releases.

For further context, the Django Chat podcast co-hosted by Django Fellow Carlton Gibson has episodes on Django Versions and Django Security Releases.

Asynchronous Views, Middleware, Tests

With version 3.0, Django began its async journey in earnest with ASGI support. In 3.1, Django now supports a fully asynchronous request path with views, middleware, and tests/test client.

A basic example, provided in the docs, is to make a request that waits for half a second and then returns a response.

# views.py
async def my_view(request):
    await asyncio.sleep(0.5)
    return HttpResponse('Hello, async world!')

This works whether you are running WSGI or ASGI mode, which was first added in 3.0.

A more relevant example would be to asynchronously fetch a URL in Django using HTTPX, the next-generation version of the popular requests library.

Cross-db JSONField

JSONField support for models and forms has now been extended to all Django-supported backends (MariaDB, MySQL, Oracle, and SQLite), not just PostgreSQL. This provides full support for JSONField queries.

# models.py
from django.db import models 

class SoccerInfo(models.Model):
    data = models.JSONField()

SoccerInfo.objects.create(data={
    'team': 'Liverpool',
    'coaches': ['Klopp', 'Krawietz'],
    'players': {'forwards': ['Salah', 'Firmino', 'Mané']},
})
SoccerInfo.objects.filter(
    data__team='Liverpool',
    data__coaches__contains='Klopp',
    data__players__has_key='forwards',
).delete()

Admin Layout

The admin now has a sidebar on the lefthand side for easier navigation on large screens. The historical breadcrumbs pattern is still available. If you'd like to disable the new sidebar, set AdminSite.enable_nav_sidebar to False.

Here is the older admin view:

3.0 Admin

And here is the new admin view with sidebar:

3.1 Admin

pathlib

Django has switched from using os.path to the more modern and concise pathlib. If you create a new project using the startproject command, the automatically generated settings.py file now defaults to pathlib.

Here is the Django 3.0 version:

# settings.py
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

And here is the newer Django 3.1 version:

# settings.py
from pathlib import Path

BASE_DIR = Path(__file__).resolve(strict=True).parent.parent

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

SECURE_REFERRER_POLICY

The SECURE_REFERRER_POLICY now defaults to 'same-origin', which is more secure. This is one of many steps the Django team makes around security. You can--and should--run the Django deployment checklist to ensure your project is secure before pushing to production: python manage.py check --deploy.

Conclusion

There are many more new features, extensively documented in the official release notes, which are well-worth reading in full as well as the accompanying Django 3.1 documentation.

Every major new Django release is a team effort and 3.1 is no exception. The Django Fellows, Carlton Gibson and Mariusz Feliask, are responsible for an enormous amount of work to ensure the release process occurs smoothly and on time. Particular thanks are due to Andrew Godwin for his work on async features and Sage Abdullah for adding cross-db JSONFields.

If you'd like to support the continued development of Django, please do so on the official fundraising page or by becoming a GitHub Sponsor.