urls get_context_data example createview based django django-views

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 .