J'ai la méthode suivante:
def _attempt(actor):
if actor.__class__ != User:
raise TypeError
Qui s'appelle d'une vue:
self.object.attempt(self.request.user)
Comme vous pouvez le voir, la méthode _attempt s'attend à ce que l'acteur soit de type Django.contrib.auth.models.User
, mais l'objet semble être de type Django.utils.functional.SimpleLazyObject
. Pourquoi cela est-il ainsi? Et plus important encore, comment puis-je convertir le LazyObject
(qui est apparemment une sorte de wrapper pour un objet User) en un objet User
?
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 le request.user
devrait être un objet User
...
====== Post-édition =====
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 cela est-il ainsi?
Voir ma réponse à une question similaire .
Django lazy charge request.user
De sorte qu'il puisse être User
ou AnonymousUser
selon l'état d'authentification. Il ne "se réveille" et retourne la classe appropriée que lorsqu'un attribut y est accédé. Malheureusement, __class__
Ne compte pas car il s'agit d'un attribut de classe primitif. Il peut arriver que vous ayez besoin de savoir qu'il s'agit en fait d'un type SimpleLazyObject
, et qu'il serait donc erroné de le proxyer sur User
ou AnonymousUser
.
Long et court, vous ne pouvez tout simplement pas faire cette comparaison telle que vous l'avez. Mais qu'essayez-vous vraiment de réaliser ici? Si vous essayez de vérifier s'il s'agit d'un User
ou AnonymousUser
, il y a request.user.is_authenticated()
pour cela, par exemple.
En règle générale, vous ne devez pas abuser de la frappe de canard. Un paramètre doit toujours être un type ou un sous-type particulier (User
ou UserSubClass
), même s'il n'a pas être. Sinon, vous vous retrouvez avec du code confus et cassant.
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. (SimpleLazyObjects ne sont pas picklables!)
user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user
Ensuite, vous utilisez user
au lieu de request.user
.
Ceci est similaire à la réponse de UsAaR33, mais une doublure est plus agréable pour convertir l'objet.
Pour toute personne souhaitant écrire un "petit" test non conforme pour votre code, vous pouvez générer un User
encapsulé et le placer dans une demande.
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:
https://github.com/Django/django/blob/master/tests/utils_tests/test_lazyobject.py pour les tests en cours sur les objets paresseux.
https://docs.djangoproject.com/en/dev/topics/testing/advanced/#Django.test.RequestFactory pour les dernières informations sur le RequestFactory
.