73 votes

request.user renvoie un SimpleLazyObject, comment le "réveiller" ?

J'ai la méthode suivante :

def _attempt(actor):
    if actor.__class__ != User:
        raise TypeError

Qui est appelé à partir d'une vue :

self.object.attempt(self.request.user)

Comme vous pouvez le voir, la méthode _attempt s'attend à ce que actor soit de type django.contrib.auth.models.User Cependant, l'objet semble être de type django.utils.functional.SimpleLazyObject . Pourquoi en est-il ainsi ? Et surtout, comment puis-je convertir le LazyObject (qui est apparemment une sorte d'enveloppe pour un objet Utilisateur) en un objet User objet ?

Plus d'informations sur Request.user est disponible ici : https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.user Cette documentation semble indiquer que le request.user devrait être un User objet...

\======Post-edit=====

J'ai maintenant la méthode suivante :

def _attempt(obj, action, actor, msg): 
    actor.is_authenticated() 
    if isinstance(actor, LazyObject): 
        print type(actor) 

Je passe un utilisateur, mais le if est toujours vraie, l'acteur est toujours un LazyObject . Pourquoi en est-il ainsi ?

46voto

Chris Pratt Points 53859

Ver ma réponse à une question similaire .

Chargements paresseux de Django request.user afin qu'il puisse être soit User o AnonymousUser en fonction de l'état de l'authentification. Elle ne se "réveille" et ne renvoie la classe appropriée que lorsqu'on accède à un attribut sur elle. Malheureusement, __class__ ne compte pas car c'est un attribut de classe primitif. Dans certains cas, vous aurez besoin de savoir qu'il s'agit en fait d'un attribut de classe primitive. SimpleLazyObject et, par conséquent, il serait erroné de le transmettre par procuration aux User o AnonymousUser .

En bref, vous ne pouvez tout simplement pas faire cette comparaison telle qu'elle est. Mais, qu'est-ce que vous vraiment que vous essayez d'atteindre ici ? Si vous essayez de vérifier si c'est un User o AnonymousUser il y a request.user.is_authenticated() pour cela, par exemple.

En règle générale, cependant, il ne faut pas abuser de la frappe des canards. Un paramètre doit toujours être un type ou un sous-type particulier ( User o UserSubClass ), même s'il ne ont pour être. Sinon, vous vous retrouvez avec un code confus et fragile.

2 votes

Merci pour votre réponse Chris. En effet, j'essaie de vérifier s'il s'agit d'un utilisateur ou d'un AnonymousUser. J'ai maintenant la méthode suivante : def _attempt(obj, action, actor, msg): actor.is_authenticated() if isinstance(actor, LazyObject): print type(actor) Je passe un utilisateur, mais la condition if est toujours vraie, l'acteur est toujours un LazyObject. Pourquoi en est-il ainsi ?

0 votes

Je réalise que je pourrais faire un try : on actor.isauthenticated() et ensuite attraper une AttributeException, qui indiquerait que actor n'a pas de méthode isauthenticated (et donc n'est pas un utilisateur). Mais je suis toujours un peu perplexe sur la raison pour laquelle le bout de code dans mon commentaire précédent ne fonctionne pas.

0 votes

Il est travailler, dans un sens ; __class__ renvoie exactement ce qu'il devrait renvoyer, SimpleLazyObject parce que c'est ce que la classe est .

21voto

UsAaR33 Points 1036

Cela devrait le faire :

# handle django 1.4 pickling bug
if hasattr(user, '_wrapped') and hasattr(user, '_setup'):
    if user._wrapped.__class__ == object:
        user._setup()
    user = user._wrapped

J'ai dû écrire ceci pour pouvoir ajouter un utilisateur au dictionnaire de session. (Les SimpleLazyObjects ne sont pas picklables !)

11voto

André Staltz Points 1023
user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user

Ensuite, vous utilisez user au lieu de request.user .

Cette réponse est similaire à celle d'UsAaR33, mais une seule ligne est plus agréable pour convertir l'objet.

4 votes

C'est similaire mais il ne tente pas d'appeler _setup() sur l'objet utilisateur si le _wrapped n'est pas initialisée correctement. Je pense que la réponse d'UsAaR33 est préférable pour cette raison.

4voto

jamesc Points 1076

Pour quiconque souhaite écrire un "petit" unittest défaillant pour son code, vous pouvez générer un wrapped User et le mettre dans une requête.

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)

Voir :

1voto

James Brewer Points 21

Cela pourrait être utile à d'autres et un peu plus propre.

La méthode python isinstance(instance, classe) renvoie si l'instance contenue dans SimpleLazyObject est de la classe fournie.

if isinstance(request.user, User):
    user = request.user

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X