是否有Django视图装饰器检查不假设输入是用户的条件?

时间:2015-03-04 21:57:07

标签: python django python-decorators django-permissions

我有一个非常简单的Django装饰器my_decorator1,如下所示:

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

我的Django APIView看起来像这样:

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.
        """

现在我想让装饰者授予对MyApiView的访问 iff self.my_val == 1.否则它应该给出一个权限被拒绝错误(403)。我该怎么做?我需要它来取代@what_decorator_goes_here。这不是工作流程的罕见现象。

我可以用于此目的的预先编写的django装饰器吗?我见过的两个similar ones@user_passes_test@permission_required。但是它们都没有在self参数上运行。第一个假设输入是User,第二个假设不同。

2 个答案:

答案 0 :(得分:1)

只返回一个HttpResponseForbidden响应对象:

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

或更复杂:

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)
[...]

虽然我必须说,我不太喜欢使用装饰器来完成此操作,而不是相应地调度请求的通用视图基类。

答案 1 :(得分:0)

我认为你应该能够从装饰器本身提出一个PermissionDenied Exception。

from django.core.exceptions import PermissionDenied

def my_decorator_1(function):
    @wraps(function)
    def decorator(self, *args, **kwargs):
        self.my_val = random.randint(0,1)
        if self.my_val == 1:
            raise PermissionDenied
        return function(self, *args, **kwargs)
    return decorator

我认为你提到的装饰者是如何工作的。然后,Django请求管道将获取异常并相应地处理它。