views:

128

answers:

2

I'm creating a decorator for Django views that will check permissions in a non-Django-managed database. Here is the decorator:

def check_ownership(failure_redirect_url='/', *args, **kwargs):
    def _check_ownership(view):
        def _wrapper(request, csi=None):
            try:
                opb_id=request.user.get_profile().opb_id
                if opb_id and csi and model.is_users_server(opb_id, csi):
                    return view(*args, **kwargs)
            except Exception, e:
                logger.debug("Exception checking ownership: %s", str(e))
            return HttpResponseRedirect(failure_redirect_url)
        _wrapper.__dict__=view.__dict__
        _wrapper.__doc__=view.__doc__
        return _wrapper
    return _check_ownership

And this is how it is being used:

@check_ownership
def my_view(request, csi=None):
    """Process my request"""

check_ownership() is being called and returning _check_ownership(). When _check_ownership() is called, it is being called with a WSGIRequest object which is what I would have expected _wrapper() to be called with. Anybody have any idea where my method has gone and how I can get it back? I don't have a way to chain to the next decorator or the actual view the way things stand.

Oh, Python 2.4.3 on CentOS and Django 1.1.1.

I want my function back! ;)

Thanks.

tj

+1  A: 
@check_ownership
def my_view(request, csi=None):
    ...

Translates into:

def my_view(request, csi=None):
    ...
my_view = check_ownership(my_view)

but check_ownership does not accept a function, but _check_ownership does. This might be where your problem lies.

stefanw
A: 

So the issue has to do with how the decorator is being called. You get different behavior with these:

@my_decorator

versus

@my_decorator(someparam='someval')

In the first case, you get the callable passed directly to my_decorator. In the second case, you don't, but the callable you return from my_decorator will.

I'm sure there is some esoteric reason for this, but it is, IMNSO, lame. It makes creating decorators with default arguments much less clear than they ought to be.

Travis Jensen