Reputation: 5025
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!
Upvotes: 4
Views: 1763
Reputation: 5025
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
Upvotes: 0
Reputation: 19432
Use method_decorator
on the dispatch() method: https://docs.djangoproject.com/en/dev/topics/class-based-views/#decorating-class-based-views
from django.utils.decorators import method_decorator
class ClassBasedView(View):
@method_decorator(rules_permission_required)
def dispatch(self, *args, **kwargs):
return super(ClassBasedView, self).dispatch(*args, **kwargs)
Or you could decorate the output of the as_view
class method, either in your url config (as described in the link above), or by saving the instance into a variable.
class ClassBasedView(View):
def dispatch(self, *args, **kwargs):
return super(ClassBasedView, self).dispatch(*args, **kwargs)
class_based_view = rules_permission_required(ClassBasedView.as_view())
Though I'm not quite sure whether the last example could cause thread safety problems (depends on how Django handles the instances). The best way is probably to stick with the method_decorator
.
Upvotes: 7