I'm curious how this code actually works. In particular what does request.__class__.user = LazyUser()
do as opposed to setattr(request, user, LazyUser())
. Sorry if this is an ignorant question, I want to know because I'm going to implement a similar piece of middleware that adds an attribute to the request.
Here's the code, and of course when you call request.user
you're returned some sort of user object.
class LazyUser(object):
def __get__(self, request, obj_type=None):
if not hasattr(request, '_cached_user'):
from django.contrib.auth import get_user
request._cached_user = get_user(request)
return request._cached_user
class AuthenticationMiddleware(object):
def process_request(self, request):
assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
request.__class__.user = LazyUser()
开发者_如何学Go return None
Update: Doing a little reading, I understand how the __get__
bit works, so my question boils down to why do this vs. using setattr()
as I mentioned above. Why is adding user
as a property of the object vs the instance a good idea?
In this case, since LazyUser() is a class that figures out if the request object already has checked to make sure the user has been queried for, this is the real magic, it only needs to query the db for the user once per session. Being a property, it is a universal action that will be applied to all instances of the request. Properties are the same across all instances of said object. This simply makes the user property an instance of LazyUser allowing only one instance of it in memory (iirc this part, someone else should be able to clarify this point).
Why is adding user as a property of the object vs the instance a good idea?
It is necessary, so the __get__ method is called via the descriptor protocol. See here.
精彩评论