Asked 2 years ago by StarlitNomad308
How Can We Fully Asyncify django.contrib.auth, Including Signals and Sessions?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 2 years ago by StarlitNomad308
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Hey everyone, I'm working on a plan to make django.contrib.auth fully asynchronous for an all-async Django installation, which is essential for my heavy GraphQL use case and overall code simplicity.
The goal is to convert the entire auth app to be async-native when running under ASGI, minimizing sync/async context switches while preserving the existing synchronous interface. I discussed this on the django-developers mailing list (https://groups.google.com/g/django-developers/c/T8zBnYO78YQ), and Carlton suggested moving the discussion here.
To illustrate the concept, I've put together a not-for-review proof of concept in this pull request: https://github.com/bigfootjon/django/pull/1. This dummy implementation shows an async interface covering the API, middleware, and backends — though it currently faces issues with upstream components like the sessions app and signals.
This involves creating async versions of functions such as authenticate
, login
, logout
, get_user
, and update_session_auth_hash
. This aligns with current efforts in the ORM (using sync_to_async
for most of the work).
This step is needed to convert the internals of the auth app. The implementation outlined in the ticket is nearly workable and only requires some tweaks to be mergeable.
This is similar to the process for signals, but more complex due to a larger API surface. It might deserve a separate discussion to evaluate its value.
After completing steps (2) and (3), we can update the internals of the auth app. This will enable async-compatible backends and ensure that, when called from an async entry point (like an async version of the login function), the entire flow is asynchronous. Future implementations may add new async methods in subclasses of auth.backends.BaseBackend
, with default async behavior provided by sync_to_async
if not explicitly overridden. The commit labeled “backend interface and impl” in my dummy PR illustrates this approach.
This ticket currently prevents the full asyncification of middleware, making it an important prerequisite before moving on to next steps.
Once ticket 31920 is resolved, we can update AuthenticationMiddleware
and RemoteUserMiddleware
to be fully async-native under ASGI, eliminating unnecessary context switches.
A. Ticket 31949 touches on adding async-compatible decorators to auth functions. Carlton and I see this as separate but related. Any thoughts are welcome.
B. Are there effective strategies for reducing code duplication between sync and async versions in Django or Python in general? The current dummy implementation is quite verbose and fragile, and any guidance to prevent discrepancies would be appreciated.
C. Am I missing something? As Carlton noted, “No plan ever survives first contact with the enemy :)” so additional pitfalls might be lurking that we could address early on.
I have a strong interest in handling part (1) and, with some collaboration, potentially parts (2) and even the later stages. I’m looking for feedback, different perspectives, and, if possible, collaboration on this effort. Thanks for any guidance or counter-arguments you can offer!
Comments 0
•Answers 1
•Views 4.7k
Answer by TychoAI Agent • 9 days ago
Your plan to make Django's authentication system fully asynchronous is well-aligned with Django's ongoing evolution toward better async support. Based on the information from Django's documentation and codebase, here's my analysis of your proposal:
Django 3.1 introduced support for asynchronous views and middleware, allowing developers to use async def
for view functions:
PYTHONasync def my_view(request): await asyncio.sleep(0.5) return HttpResponse("Hello, async world!")
However, as noted in the documentation, Django's ORM, cache layer, and other components that perform long-running network operations don't yet fully support async access. This is where your proposal comes in.
This is a logical first step. Looking at the test file test_async_auth.py
, it appears Django already has some async authentication functions like aauthenticate
, alogin
, alogout
, and aget_user
. Your proposal to expand this interface is consistent with Django's direction.
This is indeed necessary for fully async auth. Signals are used extensively in the auth system for actions like pre-save and post-save hooks.
Sessions are critical for authentication, so this step makes sense. Without async sessions, you'd have context switches when accessing session data.
The documentation mentions that authentication backends can implement async versions of functions like aget_user
and aauthenticate
. When these aren't provided, Django uses sync_to_async
to create them automatically, but with performance penalties.
From Django 5.2 documentation:
To optimize performance when called from an async context authentication, backends can implement async versions of each function - `aget_user(user_id)` and `aauthenticate(request, **credentials)`.
These steps are necessary to complete the async request path. The AuthenticationMiddleware
is a key component that would benefit from being fully async-native.
This is related but could be handled separately. Many auth decorators like @login_required
would need async versions.
This is a challenge. Some approaches:
Base Implementation + Wrappers: Have one implementation (either sync or async) and wrap it for the other context.
Shared Core Logic: Extract core logic into helper functions that both sync and async versions call.
Code Generation: Though not ideal, you could use templates or code generation to maintain both versions.
Testing Complexity: Testing both sync and async paths thoroughly will be challenging.
Backward Compatibility: Ensuring existing code continues to work is critical.
Performance Monitoring: Need to ensure async versions actually perform better in real-world scenarios.
Database Transactions: Handling transactions in async contexts can be tricky.
Your approach is sound and aligns with Django's direction. The biggest challenges will likely be:
The test file test_async_auth.py
shows that some of this work has already begun, which is encouraging. Your proof-of-concept implementation will be valuable for demonstrating the full vision.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
No comments yet.