Wednesday, April 11, 2012

How to write a decorator for a class based view -- permision based on object from view

right now I'm using this app for permission checking: django-rules


However it hasn't been updated for over a year now and there's no decorator for the "new" (since django 1.3) class based views. I would like to be able to use at the urls.py like this:


url(r'^casos/(?P<pk>\d+)/editar/$', rules_permission_required('lawsuits.logical_check', raise_exception=True)(CaseUpdateView.as_view()), name='case_edit'),
 


I can't figure out how to get the object from the class based view from the decorator. Do you guys have any idea? Here's what I have so far:


from django.utils.decorators import available_attrs
 def rules_permission_required(perm, queryset=None, login_url=None, raise_exception=False):
     def wrapper(view_func):
         @wraps(view_func, assigned=available_attrs(view_func))
         def inner(request, *args, **kwargs):
             #view_func is the class based view -> <function MyEditView at 0x94e54c4>
 
             print view_func.get_object() # doesnt work
             print view_func(request, *args, **kwargs).get_object() # doesnt work either
 
             #any ideas?
 
             if not request.user.has_perm(perm, obj=obj):
                 return redirect_to_login(request, login_url, raise_exception)
             return view_func(request, *args, **kwargs)
         return inner
     return wrapper
 


Many thanks in advance!


 
 
Answer:
I ended up using a class decorator
def rules_permission_required(perm, queryset=None, login_url=None, raise_exception=False):

    def wrapper(cls):                
        def view_wrapper(view_func):
            @wraps(view_func, assigned=available_attrs(view_func))
            def inner(self, request, *args, **kwargs):
                # get object
                obj = get_object_from_classbased_instance(
                        self, queryset, request, *args, **kwargs
                    )

                # do anything you want
            return inner
        cls.dispatch = view_wrapper(cls.dispatch)
        return cls
    return wrapper

No comments:

Post a Comment