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

发布于 2021-01-29 15:06:52

我正在尝试由两个装饰器装饰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装饰器不同?

关注者
0
被浏览
79
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    现在,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
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看