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?
Then you use
user
instead ofrequest.user
.This is similar to UsAaR33's answer, but a one-liner is nicer for converting the object.
For anyone wanting to write a failing "small" unittest for your code, you can generate a wrapped
User
and stuff it inside a request.See:
https://github.com/django/django/blob/master/tests/utils_tests/test_lazyobject.py for current tests on the Lazy Objects.
https://docs.djangoproject.com/en/dev/topics/testing/advanced/#django.test.RequestFactory for latest info on the
RequestFactory
.This should do it:
I had to write this so I could add a user to the session dictionary. (SimpleLazyObjects are not picklable!)
See my answer on a similar question.
Django lazy loads
request.user
so that it can be eitherUser
orAnonymousUser
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 aSimpleLazyObject
type, and therefore it would be wrong to proxy it on toUser
orAnonymousUser
.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
orAnonymousUser
, there'srequest.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
orUserSubClass
), even though it doesn't have to be. Otherwise, you end up with confusing and brittle code.