小编典典

Django中一个视图的多个装饰器:执行顺序

python

我正在尝试由两个装饰器装饰Django视图,一个装饰器用于检查登录,另一个用于检查is_active。

第一个是内置的@login_required,第二个如下:

def active_required(function):
    dec = user_passes_test(lambda u: u.is_active, '/notallowed', '')
    return dec(function)

现在,Python中的装饰器可以由内而外工作,但是以下操作不起作用:

@active_required
@login_required
def foo(request):
    ...

我想首先检查用户是否已登录,如果没有,请重定向到登录页面,如果他或她已登录,则要检查他或她是否处于活动状态,如果不是,则执行重定向到'/notallowed'

发生的情况是,如果login_required失败,则不会将用户重定向到登录页面,而是@active_required会执行该用户,并且由于在这种情况下用户为null,@
active_required装饰器将失败,并将用户重定向到/notallowed

更改顺序似乎可行,

@login_required
@active_required
def foo(request):
    ...

但我怀疑这种方法也有问题。

组合两个装饰器的正确方法是什么,为什么执行顺序与简单的Python装饰器不同?


阅读 238

收藏
2021-01-20

共1个答案

小编典典

现在,Python中的装饰器由内而外地工作

好吧,我想这取决于您由内而外的定义。对于您的情况,您要@login_required首先执行,因此它应该是“最外面的”(顶部)装饰器。

如您所述,您的最后一个示例有效,并且确实是实现此目的的正确方法。

编辑

困惑可能是这些特定装饰器的工作方式。

@login_required(@original_view) 返回一个新视图,该视图首先检查您是否已登录,然后调用original_view

所以

    @login_required(
        @active_required(
            @my_view
        )
    )



first checks if you are logged in, then
    first(second) checks if you are active, then
        runs my_view
2021-01-20