To anyone that uses Django and works with lots of data from lots of different Web sources, this is a big deal. Supporting asynchronous views means cleaner code, a different way to think about things, and most importantly, the ability to dramatically improve performance of applications.
But let’s back up a bit.
If you’re unfamiliar with the term “views”, don’t worry, it’s an easy concept to understand.
Views are key components of applications built in with the Django framework. At their very simplest, views are Python functions or classes that take a web request and produce a web response. Prior to Django 3.1, views had to run with Python threads. Now, views can run in an asynchronous event loop without Python threads. This means Python’s asyncio library can be used inside of Django views.
According to the documentation:
The main benefits are the ability to service hundreds of connections without using Python threads.
There are other benefits as well including the use of Python’s asyncio.gather.
Let’s say you have a view that makes four API calls. Even in a best case scenario, if each call takes only a second, it’s a total of four seconds if executed synchronously. And that’s the best case scenario.
We can cut down on that time frame significantly and improve the situation overall by using Pythons concurrent.futures library.
This makes it possible to make the four API calls in the previous example concurrently meaning the view could take roughly one second in total if using four workers with the ThreadPoolExecutor. By all accounts, the practice cuts down on the time needed and improves the calls.
That’s important in a world where seconds matter and making someone wait around for an application to load can cause frustration.
A Real-World Example: Tracking Montana’s Yellowstone River
To illustrate how asynchronous views improve performance, I created an example project to display statistical data from the United States Geological Survey (USGS).
The project makes six API calls to the USGS to collect data about six access points on the Yellowstone River in my home state of Montana. This data includes the volume of water moving at each access point at the time, known as discharge rate, as well as the gage height, which is the surface level of the water relative to its streambed.
Example 1: The Synchronous Method
The data loads and takes almost four seconds. For the purposes of this post, that’ll be our baseline. Let’s see if we can improve that situation.
Example 2: A Concurrent View Loading Some Data Simultaneously
Now we’re down to roughly 1.5 seconds and that’s a big improvement. Let’s see what happens when we leverage asynchronous views.
Example 3: The Asynchronous Method
Wow, we got results back in just under a second. That’s roughly a three second improvement on the original method.
This example shows pretty clearly how asynchronous views can be leveraged to drastically improve performance.
View the full project on GitLab: https://gitlab.com/nextlink/example-django-async-rivers