user_passes_test:如果用户未通过则引发异常

时间:2017-04-05 09:02:04

标签: python django authentication django-1.4

我正在尝试定义一个装饰器来检查用户是否具有管理员某些权限:

def admin_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
    actual_decorator = user_passes_test(
        lambda u: u.is_staff and u.is_authenticated() and not Association.objects.filter(admins=u).exists(),
        login_url=login_url,
        redirect_field_name=redirect_field_name
    )
    if function:
        return actual_decorator(function)
    return actual_decorator

目的是通过观点来使用它。特别是,我在基于类的视图中使用它:

class MyCBV(CreateView):
    @method_decorator(admin_required)
    def dispatch(self, request, *args, **kwargs):
        return super(MyCBV, self).dispatch(request, *args, **kwargs)

问题是此视图是通过AJAX加载的,因此重定向不会发生。此外,即使用户身份验证失败,视图返回的HTTP状态也会成功,因此客户端(JS)无法确定操作何时成功。

我通常无法理解装饰器和Django身份验证,因此我的问题是:当身份验证修饰函数失败时,如何引发异常(最好是PermissionDenied异常)?

1 个答案:

答案 0 :(得分:1)

在Django 1.9+中,您可以使用UserPassesTestMixin代替装饰器,并将raise_exception设置为True

由于您使用的是不安全且过时的Django 1.4,因此您无法做到这一点。没有选项可以使user_passes_test加注PermissionDenied而不是重定向。您可以尝试检测JavaScript中的重定向,也可以查看user_passes_test源代码并实现类似的返回所需响应的内容。