django: цель django.utils.functional.SimpleLazyObject?
Я столкнулся с проблемой, где я назначил request.user
к переменной с именем prior_user
затем аутентифицировал пользователя, затем проверил, request.user != prior_user
, Я ожидал, что они не будут такими же, и что prior_user
должен содержать `AnonymousUser. К моему удивлению, они были одинаковыми.
Образец кода:
prior_user = request.user # request object, obtained froma view
authenticate_user(request) # some function that authenticates
print prior_user.username != request.user.username # returns False i.e.they are the same!
Затем я обнаружил, что prior_user на самом деле содержит экземпляр django.utils.functional.SimpleLazyObject, поэтому я предполагаю, что это своего рода ленивый тип поиска, т. Е. Значение prior_user не ищется до тех пор, пока оно фактически не используется. Глядя на исходный код, я не могу это подтвердить.
Любой, кто имеет опыт работы с Django, может рассказать мне, что происходит и зачем это нужно?
Это оставляет меня немного потрясенным, потому что обычный оператор присваивания не работает так, как я ожидаю, и что еще в Django ведет себя так? Я также не видел, как это описано в документации.
Так кто-нибудь со сверхчеловеческим знанием Джанго может дать некоторую ясность?
1 ответ
auth
промежуточное ПО добавляет user
приписывать request
это пример SimpleLazyObject
, SimpleLazyObject
сам по себе является подклассом LazyObject
, LazyObject
как описано в фактическом коде:
Оболочка для другого класса, которая может использоваться для отсрочки создания экземпляра обернутого класса
SimpleLazyObject
просто устанавливает этот класс (_wrapped
атрибут на LazyObject
через метод, в данном случае, get_user
, Вот код для этого метода:
def get_user(request):
if not hasattr(request, '_cached_user'):
request._cached_user = auth.get_user(request)
return request._cached_user
Это само по себе является просто оберткой вокруг auth.get_user
Это позволяет использовать механизм кэширования. Итак, вот что на самом деле запускается:
def get_user(request):
from django.contrib.auth.models import AnonymousUser
try:
user_id = request.session[SESSION_KEY]
backend_path = request.session[BACKEND_SESSION_KEY]
backend = load_backend(backend_path)
user = backend.get_user(user_id) or AnonymousUser()
except KeyError:
user = AnonymousUser()
return user
Итак, все, что на самом деле происходит здесь, это request.user
неоднозначно, пока на самом деле не используется для чего-то. Это важно, поскольку позволяет адаптировать его в зависимости от текущего статуса аутентификации. Если вы обращаетесь к свойству до его аутентификации, он возвращает экземпляр AnonymousUser
, но если вы аутентифицируетесь и затем получаете доступ к нему, он возвращает экземпляр User
,