Nearly all pages in my Django application require authentication. The app uses Django's AuthenticationMiddleware, so on every request the application hits the DB to retrieve the authenticated user.
I recently started storing session data in a Redis-backed cache. Since that has been working out great, eliminating one DB query per request by fetching session data from the cache, I'm wondering if I could also store authenticated users in Redis as well?
I am considering implementing this with a custom authentication backend, which would just subclass Django's ModelBackend, overriding the get_user()
method:
# backends.py
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
class MyAuthBackend(ModelBackend):
def get_user(self, user_id):
user = get_user_from_cache(user_id) # not implemented here
if user is None:
UserModel = get_user_model()
try:
user = UserModel._default_manager.get(pk=user_id)
except UserModel.DoesNotExist:
return None
else:
set_user_in_cache(user) # not implemented here
return user
Hooking this up in settings:
# settings.py
AUTHENTICATION_BACKENDS = ('myapp.backends.MyAuthBackend',)
I should also probably note:
I probably don't intend to cache the entire user object. Instead, this will probably just cache a basic dictionary that contains only the user info that the application need on every page (like the user_id, name, etc). So the user
attribute added to every incoming request
object by Django's AuthenticationMiddleware will not be an instance of my user model.
Is this a good idea? Are there any downsides? And, if it's okay, is this the preferred way of accomplishing this?
Thanks a lot!
Update:
I've been caching user data successfully in Redis for a while now. However, instead of creating a custom authentication backend as I originally planned and described in the question, I completely replaced django's AuthenticationMiddleware instead.
The inspiration came from this package and my implementation is very similar.