← All posts

Django Async: What's new and what's next?

All that you need to know about async support added in the latest Django 3.1.

Header image
By Sanket on 
Share on Twitter Share on LinkedIn Share on Facebook

Starting with Django 3.1, the latest version that dropped a couple of weeks ago, Django now supports fully asynchronous request path. This is exciting for everyone who’s been waiting on the edge of their seats ever since Andrew Godwin’s DEP 0009 was approved by Django Technical Board in July 2019. Read on to know all about what this release means if you have a Django application in production and looking to add async support. At DeepSource, we’re working on adding more Django issues in our Python analyzer, which will also include async-specific bug risks and anti-patterns.

Support for asynchronous views and middleware

In Django 3.1, async features are now supported across the request-response cycle. This means you can define fully asynchronous views using the async keyword:

async def get_cat_facts(request):
  """Return a random cat fact."""
  async with aiohttp.ClientSession() as session:
    async with session.get('https://catfact.ninja/fact') as resp:
      data = await resp.json()
  return data

The most exciting thing about this is that async support is entirely backwards-compatible. This means you can use any combination of async and sync views, and Django will guarantee that the execution is always done in the right execution context. So if you want to dip your hands without porting everything right away, you can just flip the switch and add just one async view, without any speed regressions on the existing synchronous code.

You can also use the goodness of async in your middleware functions:

def simple_middleware(get_response):
  async def middleware(request):
    # do something interesting
    response = await get_response(request)
    return response
  return middleware

Since middleware can support any combination of sync and async requests, Django will try to fit the middleware’s requirements if only one type of requests are supported (like only async requests in the example above) — but at a performance penalty. It is recommended to use the sync_and_async_middleware decorator to define middleware that support both kinds of requests. More examples can be found in the docs.

Is ASGI required?

All of Django’s async features are fully supported on both WSGI and ASGI — although there will be performance penalties if you run async code with WSGI and long-running requests won’t be efficient. If you want to make your sync code work well with your all-new async views and ASGI mode, use of the sync_to_async decorator is recommended.

Where to use async views?

If you are doing a lot of external HTTP calls from a view, async views allow you to natively make those calls in parallel. This can provide great speed bumps, especially if you had been using async code inside sync views before. If your views involve heavy-lifting calculations or long-running network calls to be done as part of the request path, it’s a great use case for using async views.

Where you can’t use async in Django yet

The ORM, cache layer, and several other parts of code that involve long-running network calls do not support async yet. Support for async features in the ORM is expected to come sooner as it is a part of the initial DEP. Features like templating and cache backends will need some more time, as those will need their own separate DEPs and research to be fully async.

Conclusion

Django 3.0 started the journey of bringing full async capability to Django, starting with adding support for ASGI which could run sync code. With this release, you can actually put async code in production if you don’t have to do heavy-lifting with some parts of Django that don’t support async yet. The fact that all changes are guaranteed to be 100% backward compatible is an impressive feat in itself — and it reassures the bright future of full async support in Django soon!

About DeepSource
DeepSource helps you automatically find and fix issues in your code during code reviews, such as bug risks, anti-patterns, performance issues, and security flaws. It takes less than 5 minutes to set up with your Bitbucket, GitHub, or GitLab account. It works for Python, Go, Ruby, and JavaScript.
Get started for free

Keep reading...