tags:

views:

124

answers:

3

Here's a template filter that has been working without problems till recently, before I updated Django source:

from pm_core.models import PMUser 
@register.filter 
def can_manage_market(user, market): 
    if not isinstance(user, PMUser): return False 
    return user.can_manage_market(market)

The filter has begun to return false always. The problem seems to be that the 'user' instance is of 'SimpleLazyObject' instead of PMUser (a subclass of User). Searching it up on the internet brought me to Ticket #12049, which indicates that this may be a similar bug (however, the patch provided there is not a remedy, unfortunately).

I'd appreciate any information on this simplelazyobject that I have not been aware of before.

ps. I have also posted this question to django-users group, but have not received an answer yet.

A: 

Changeset 11626 (checked in a few days ago) changed the 'user' definition in django.core.context_processors from ContextLazyObject to SimpleLazyObject. My coffee has not fully kicked in yet, but it looks like this might be the source of your problem. You might have to put a wrapper around this or change your test.

Peter Rowell
I receive user as a SimpleLazyObject that is wrapping the PMUser instance (_wrapper). What can be the reason that context processor has begun to provide a wrapper instead of the actual object?
shanyu
+1  A: 

As Peter says, this is due to Changeset 11626. The reason why this is now giving you a wrapper, rather than the object, is because of the 'laziness' of that wrapper object. It's designed so that if you don't actually do anything with it, it never gets the underlying User object - this is for cache optimisation reasons. Since all you're doing is checking the type, and don't evaluate the object, it remains a LazyObject and your test fails.

Rather than checking that the object is of a particular type, which is not Pythonic anyway, you should check that your object has the methods or attributes you want to call. The wrapper should pass these through transparently, and your test will now succeed.

try:
    return user.can_manage_market(market)
except AttributeError:
    return False
Daniel Roseman
Thanks, Daniel. Another issue comes to my mind, which I'll try to test: {%ifnotequal another_user user%} will always return False, if user (RequestContext's user) will not get evaluated and hence the comparison will be between a user instance provided by the view and a simplelazyobject, right?
shanyu
{%ifnotequal another_user user%} returns False. Any solutions?
shanyu
Another change has just been committed for this - does it fix your problem? If not, there's also ticket #12060 which has just been opened, which looks similar to your issue. You might consider reverting to version 1.1 until it's fixed - this is probably a good idea in any case.
Daniel Roseman
I have seen the ticket #12060, actually it refers to my post at django-users. As a quick resort, I changed the single line of code in Auth context processor which wraps the user instance and now it works without problems. I think I can survive this short period till it gets fixed.
shanyu
A: 

This issue has been filed as a bug (ticket #12060), and has officially been accepted. Thanks go to Peter and Daniel for their help.

EDIT: The issue has been fixed in changeset 11637.

shanyu