Table of contents

Django 3.1 changes and new features: complete overview

Django 3.1 changes and new features: complete overview

A few hours ago I was browsing my twitter and I found out that they just released Django 3.1, changes and new features of ; my favorite web framework. This new version has some interesting changes that I’ll talk about next.

Views, Middleware and asynchronous testing

Guess who else is betting on asynchrony? With this new update Django incorporates asynchronism in views, middleware and tests. However Django’s ORM, cache and other pieces of code that connect to the internet do not have asynchronous support for this update, although the documentation states that support will be added for later versions.


Django will recognize the views we specify with async def and will take care of executing them in an asynchronous context. To get the benefits you must use an ASGI server. On the other hand, it is also possible to use a WSGI server but there will be performance penalties.

import datetime
from django.http import HttpResponse

async def current_datetime(request):
    now =
    html = '<html><body>It is now %s.</body></html>' % now
    return HttpResponse(html)


Django now allows combining both asynchronous and synchronous middleware. By default Django will assume that your middleware is synchronous. To modify this behavior you need to change the boolean attributes of your middleware factory:

  • sync_capable (default to True)
  • async_capable (default to False)

Django now incorporates three decorators for your middleware factories. Also, if your middleware factory returns an asynchronous get_response() the appropriate syntax must be used; async def.

  • sync_only_middleware()
  • async_only_middleware()
  • y sync_and_async_middleware()
import asyncio
from django.utils.decorators import sync_and_async_middleware

def simple_middleware(get_response):
    # One-time configuration and initialization goes here.
    if asyncio.iscoroutinefunction(get_response):
        async def middleware(request):
            # Do something here!
            response = await get_response(request)
            return response

        def middleware(request):
            # Do something here!
            response = get_response(request)
            return response

    return middleware


If you are testing from an asynchronous function you must use the asynchronous test client which is available as django.test.AsyncClient, or as self.async_client. This new AsyncClient client has the same methods as the normal test client.

async def test_my_thing(self):
    response = await self.async_client.get('/some-url/')
    self.assertEqual(response.status_code, 200)

JSON compatible fields

It’s about time for a JSON field! Django now includes a field for your models called models.JSONField and a forms.JSONfield field, which can be used in any compatible database backend. Both fields support custom JSON encoders and decoders.

from django.db import models

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

    'name': 'John',
    'cities': ['London', 'Cambridge'],
    'pets': {'dogs': ['Rufus', 'Meg']},

Search in JSON fields

We can filter by this new field by searching for the contents of the JSON properties using double underscore notation.


Django gives us the ability to search for objects by the presence of specific keys at the top level of their JSON field content.


Likewise, we can search for the presence or absence of certain elements in a property with a list value



With this new update we can specify the default hashing algorithm in the file. This value will be used to encrypt cookies, password reset tokens in the admin panel, user sessions and in signatures created by django.core.signing.Signer and django.core.signing.dumps(). SHA-256 support is also added.

Other new features of Django 3.1

PASSWORD_RESET_TIMEOUT_DAYS is deprecated in favor of PASSWORD_RESET_TIMEOUT, this new configuration variable allows to define the number of seconds that a password reset link will be valid.

You can now iterate through the Paginator to get the pages.

A link to clear all filters is added to the right side panel of the admin.

The configuration variable CSRF_COOKIE_SAMESITE now allows ‘None’ as a value. While HttpResponse.set_cookie() and HttpResponse.set_signed_cookie() allow using samesite=‘None’.

Remember that if you want to see the changes to the complete documentation you can go to this link to see the complete changes in Django 3.1 version

If you want to improve your skills in Django let you here recommendations of two excellent books. Come in and check my reviews of Django for Professionals and Two scoops of Django.

Eduardo Zepeda
Web developer and GNU/Linux enthusiast always learning something new. I believe in choosing the right tool for the job and that simplicity is the ultimate sophistication. I'm under the impression that being perfect is the enemy of getting things done. I also believe in the goodnesses of cryptocurrencies outside of monetary speculation.
Read more