I have a very simple Django decorator my_decorator1
that looks like this:
def my_decorator_1(function):
@wraps(function)
def decorator(self, *args, **kwargs):
self.my_val = random.randint(0,1)
return function(self, *args, **kwargs)
return decorator
My Django APIView that looks like this:
class MyApiView(views.APIView):
@what_decorator_goes_here
@my_decorator_1
def post(self, request, *args, **kwargs):
"""
Blah Blah Blah. The rest is snipped out for brevity.
"""
Now I want a decorator to grant access to MyApiView iff self.my_val == 1. Otherwise it should give a permission denied error (403). How can I do it? I need it to replace @what_decorator_goes_here
. This can't be that uncommon of a workflow.
Isn't there a prewritten django decorator I can use for this purpose? The two similar ones that I have seen are @user_passes_test
and @permission_required
. However neither of them operate on the self
argument. The first one assumes the input is a User
and the second one takes something different.
just return a HttpResponseForbidden
response object:
from django.http import HttpResponseForbidden
def what_decorator_goes_here(function):
@wraps(function)
def check_value(self, *args, **kwargs):
if getattr(self, 'my_val', None) == 1:
return function(self, *args, **kwargs)
else:
return HttpResponseForbidden()
return check_value
Or more sophisticated:
def allow_if_view_value(attr_name, target_value):
def decorator(function):
@wraps(function)
def check_value(self, *args, **kwargs):
if getattr(self, attr_name, None) == target_value:
return function(self, *args, **kwargs)
else:
return HttpResponseForbidden()
return check_value
return decorator
@allow_if_view_value('my_val', 1)
[...]
Albeit I must say, I am not too fond of using decorators to accomplish this instead of a generic view base class that dispatches requests accordingly.