python - custom - request.user devuelve un objeto SimpleLazyObject, ¿cómo lo "despierto"?
login url django (4)
Tengo el siguiente método:
def _attempt(actor):
if actor.__class__ != User:
raise TypeError
Que se llama desde una vista:
self.object.attempt(self.request.user)
Como puede ver, el método _attempt espera que el actor sea de tipo django.contrib.auth.models.User
, sin embargo, el objeto parece ser de tipo django.utils.functional.SimpleLazyObject
. ¿Por qué esto es tan? Y, lo que es más importante, ¿cómo puedo convertir LazyObject
(que aparentemente es un tipo de envoltorio para un objeto Usuario) en un objeto User
?
Más información sobre Request.user
está disponible aquí: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.user Esta documentación parece indicar que request.user
debe ser un Objeto de User
...
====== Edición posterior =====
Tengo el siguiente método ahora:
def _attempt(obj, action, actor, msg):
actor.is_authenticated()
if isinstance(actor, LazyObject):
print type(actor)
Estoy pasando un usuario, sin embargo, if
condición sigue siendo cierta, el actor sigue siendo un LazyObject
. ¿Por qué esto es tan?
Esto debería hacerlo:
# handle django 1.4 pickling bug
if hasattr(user, ''_wrapped'') and hasattr(user, ''_setup''):
if user._wrapped.__class__ == object:
user._setup()
user = user._wrapped
Tuve que escribir esto para poder agregar un usuario al diccionario de la sesión. (SimpleLazyObjects no son seleccionables!)
Para cualquier persona que desee escribir una prueba de unidad "pequeña" para su código, puede generar un User
envuelto y rellenarlo dentro de una solicitud.
from django.contrib.auth import get_user_model
from django.test import RequestFactory
from django.utils.functional import SimpleLazyObject
user = get_user_model().objects.create_user(
username=''jacob'',
email=''jacob@…'',
password=''top_secret'',
)
factory = RequestFactory()
request = factory.get(''/'')
request.user = SimpleLazyObject(lambda: user)
Ver:
https://github.com/django/django/blob/master/tests/utils_tests/test_lazyobject.py para las pruebas actuales en los objetos perezosos.
https://docs.djangoproject.com/en/dev/topics/testing/advanced/#django.test.RequestFactory para obtener la información más reciente sobre
RequestFactory
.
Ver mi respuesta en una pregunta similar .
Django lazy carga request.user
para que pueda ser User
o User
AnonymousUser
según el estado de autenticación. Solo "despierta" y devuelve la clase apropiada cuando se accede a un atributo en él. Desafortunadamente, __class__
no cuenta porque es un atributo de clase primitivo. Hay ocasiones en las que es posible que necesite saber que este es realmente un tipo SimpleLazyObject
, y por lo tanto, sería incorrecto SimpleLazyObject
un proxy al User
o User
AnonymousUser
.
Largo y corto, simplemente no puedes hacer esta comparación como la tienes. Pero, ¿qué estás tratando de lograr realmente aquí? Si está intentando verificar si es un User
o un User
AnonymousUser
, existe request.user.is_authenticated()
para eso, por ejemplo.
Sin embargo, como regla general, no debes abusar de la escritura de pato. Un parámetro siempre debe ser un tipo o subtipo particular ( User
o UserSubClass
), aunque no tiene que serlo. De lo contrario, terminas con un código confuso y frágil.
user= request.user._wrapped if hasattr(request.user,''_wrapped'') else request.user
Luego usas user
lugar de request.user
.
Esto es similar a la respuesta de UsAaR33, pero una sola línea es mejor para convertir el objeto.