Async Support in Django(Part 2)
In the first part, we learned about ASGI and WSGI in this part we will deep dive into an async world in Django. Let’s get started….
If you haven't read Part 1 do check out!
So, Here are some popular web servers that support ASGI :
- Daphne: Daphne is an ASGI server built on top of Twisted, an event-driven networking engine for Python. It is the recommended server for running Django applications with ASGI support.
- uvicorn: uvicorn is an ASGI server based on uvloop and httptools, designed for high-performance and minimal resource usage. It is widely used for running ASGI applications, including FastAPI and Starlette.
- Hypercorn: Hypercorn is an ASGI server based on the trio event loop. It aims to be more modern and faster than other ASGI servers.
- Gunicorn: While Gunicorn (Green Unicorn) is primarily a WSGI server, it can be used to serve ASGI applications as well through the use of ASGI workers like
uvicorn
ordaphne
.
To use ASGI with your Django application, you need to ensure that your web server supports ASGI and use an ASGI server like Daphne or uvicorn to serve your Django application. Additionally, you must configure your Django project to use ASGI by specifying the ASGI application in your server configuration.
For example, using uvicorn, you can run your Django application with ASGI support using the following command:
1. Installing Uvicorn
python -m pip install uvicorn
2. Running Django in Uvicorn
You must configure your Django project to use ASGI by specifying the ASGI application in your server configuration.
uvicorn myproject.asgi:application
Here, myproject.asgi
points to the ASGI application instance in our Django project, and application
is the name of the ASGI application.
Restart the web server after making the necessary configuration changes.
For more advanced usage, read the Uvicorn documentation and Django documentation.
Async views
Async views in Django refer to the ability to define view functions using asynchronous programming paradigms. Prior to Django 3.1, Django primarily supported synchronous (blocking) views, where each request was processed sequentially and synchronously. However, starting from Django 3.1, async support was introduced as an experimental feature, allowing developers to define views using asynchronous syntax.
Async views in Django are defined using the async def
syntax instead of the traditional def
syntax used for synchronous views. By defining a view function as asynchronous, you enable the use of asynchronous programming within the view, which can be particularly useful for handling I/O-bound operations that would otherwise block the server's main execution thread.
Here is an example of async views in Django fetching Data from an External API
# views.py
from django.http import JsonResponse
import httpx
async def async_api_view(request):
async with httpx.AsyncClient() as client:
response = await client.get('https://api.example.com/data')
data = response.json()
# Perform some other asynchronous tasks
# ...
return JsonResponse(data)
In this example, the async_api_view
makes an asynchronous HTTP GET request to an external API using the httpx
library. During the API call, the server can continue processing other requests, making it more efficient.
Async ORMS
“Async ORMs” refers to Asynchronous Object-Relational Mapping libraries. In the context of web development, an ORM is a tool that allows you to interact with a database using Python classes and objects, rather than writing raw SQL queries. Async ORMs take this a step further by providing asynchronous capabilities for database operations, allowing you to work with databases using asynchronous programming paradigms.
In traditional synchronous ORMs, database operations typically block the main execution thread until the operation is completed. Asynchronous ORMs, on the other hand, allow these database operations to be performed asynchronously, enabling your application to continue processing other tasks while waiting for the database response. This is particularly useful when dealing with I/O-bound operations, such as fetching data from a remote database or making external API calls.
In the context of Django, starting from version 3.1, Django introduced experimental support for asynchronous database queries using async ORM functions. This means you can now perform asynchronous database operations in Django views, models, and other components.
Fortunately, you can do many queries using Django’s asynchronous query APIs. Every method that might block — such as get()
or delete()
- has an asynchronous variant (aget()
or adelete()
), and when you iterate over results, you can use asynchronous iteration (async for
) instead.
user = await UserProfile.objects.filter(name='django').afirst()
Query iteration (New in Django 4.1.)
The default way of iterating over a query — with for
- will result in a blocking database query behind the scenes as Django loads the results at iteration time. To fix this, you can swap to async for
:
async for entry in Authors.objects.filter(name__startswith="A"):
...
For more read async query.
Best Practices for Async Development in Django
- Understand Asynchronous Programming: Before diving into async development, make sure you have a solid understanding of asynchronous programming concepts, such as event loops, coroutines (
async
andawait
), and non-blocking I/O. Familiarize yourself with theasyncio
library and how it works with Django's ASGI support. - Use ASGI-Compatible Web Server: To serve Django applications with async support, use an ASGI-compatible web server such as Daphne or uvicorn. These servers are designed to handle asynchronous requests efficiently and work seamlessly with Django’s async views and middleware.
- Choose Async-Ready Libraries: When using third-party libraries in your Django async project, ensure they are compatible with asynchronous programming. Look for async-ready alternatives for databases, HTTP clients, and other I/O operations to avoid blocking the event loop.
- Optimize Synchronous and Asynchronous Components: Not all parts of your Django application need to be asynchronous. Identify I/O-bound operations that could benefit from async execution and focus on optimizing those areas. Use synchronous code for simple and CPU-bound tasks.
By following these best practices, you can take full advantage of asynchronous development in Django and build high-performance web applications that handle concurrency and I/O-bound tasks efficiently. As always, remember to measure the performance and benchmark your async code to verify the improvements and identify any potential issues.
Thank you for taking the time to read this article.
Share with your Django community and keep supporting!
Don’t forget to check out more articles
Async PART 1, Behind for loop in Python, How to do migrations in fastAPI
Until then, keep exploring, and keep learning!