get_context_data - httpresponse django example
django: PropĆ³sito de django.utils.functional.SimpleLazyObject? (1)
Me encontré con un problema en el que prior_user
request.user
a una variable llamada prior_user
, luego básicamente autenticé al usuario, luego verifiqué si request.user != prior_user
. Esperaba que no fueran iguales y que prior_user
debería contener `AnonymousUser. Para mi sorpresa, eran lo mismo.
Código de muestra:
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!
Luego descubrí que el usuario_previo realmente contiene una instancia de django.utils.functional.SimpleLazyObject, así que supongo que es una especie de tipo de búsqueda lenta, es decir, el valor del usuario previo no se busca hasta que se usa realmente. Al mirar el código fuente, no puedo confirmarlo.
¿Alguien con experiencia django puede decirme qué está pasando y por qué es necesario?
Esto me deja un poco alterado, porque la declaración de asignación habitual no funciona de la manera que espero y ¿qué más dentro de Django actúa así? Tampoco vi esto descrito en los docs .
Entonces, ¿alguien con un conocimiento súper humano de django puede proporcionar algo de claridad?
El middleware de auth
agrega un atributo de user
para request
que sea una instancia de SimpleLazyObject
. SimpleLazyObject
, en sí mismo es una subclase de LazyObject
. LazyObject
es, como se describe en el código actual:
Un contenedor para otra clase que se puede usar para retrasar la creación de instancias de la clase envuelta
SimpleLazyObject
simplemente establece esa clase (el atributo _wrapped
en LazyObject
) a través de un método pasado, en este caso, get_user
. Aquí está el código para ese método:
def get_user(request):
if not hasattr(request, ''_cached_user''):
request._cached_user = auth.get_user(request)
return request._cached_user
Eso en sí mismo es realmente un envoltorio alrededor de auth.get_user
, que habilita una especie de mecanismo de almacenamiento en caché. Así que aquí está lo que finalmente se ejecuta:
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
Entonces, todo lo que está sucediendo aquí es que request.user
es ambiguo hasta que realmente se usa para algo. Esto es importante, porque le permite adaptarse dependiendo del estado de autenticación actual . Si accede a una propiedad antes de autenticarse, devuelve una instancia de User
AnonymousUser
, pero si se autentica y luego accede a ella, devuelve una instancia de User
.