Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

request.user returns a SimpleLazyObject, how do I "wake" it?

I have the following method:

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

Which is called from a view:

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

As you can see, the _attempt method expects actor to be type django.contrib.auth.models.User, however the object appears to be of type django.utils.functional.SimpleLazyObject. Why is this so? And more importantly, how can I convert the LazyObject (which apparently is a kind of wrapper for a User object) into a User object?

More info on Request.user is available here: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.user This documentation seems to indicate the request.user should be a User object...

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

I've got the following method now:

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

I'm passing a user, however the if condition is still true, actor is still a LazyObject. Why is this so?

like image 482
Himerzi Avatar asked Jul 03 '12 16:07

Himerzi


2 Answers

See my answer on a similar question.

Django lazy loads request.user so that it can be either User or AnonymousUser depending on the authentication state. It only "wakes up" and returns the appropriate class when an attribute is accessed on it. Unfortunately, __class__ doesn't count because that's a primitive class attribute. There's occasions where you might need to know that this is actually a SimpleLazyObject type, and therefore it would be wrong to proxy it on to User or AnonymousUser.

Long and short, you simply can't do this comparison as you have it. But, what are you really trying to achieve here? If you're trying to check if it's a User or AnonymousUser, there's request.user.is_authenticated() for that, for example.

As a general rule though, you shouldn't abuse duck typing. A parameter should always be a particularly type or subtype (User or UserSubClass), even though it doesn't have to be. Otherwise, you end up with confusing and brittle code.

like image 84
Chris Pratt Avatar answered Sep 20 '22 23:09

Chris Pratt


This should do it:

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

I had to write this so I could add a user to the session dictionary. (SimpleLazyObjects are not picklable!)

like image 43
UsAaR33 Avatar answered Sep 23 '22 23:09

UsAaR33