我正在尝试由两个装饰器装饰Django视图,一个装饰器用于检查登录,另一个用于检查is_active。
第一个是内置的@login_required,第二个如下:
@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'。
'/notallowed'
发生的情况是,如果login_required失败,则不会将用户重定向到登录页面,而是@active_required会执行该用户,并且由于在这种情况下用户为null,@ active_required装饰器将失败,并将用户重定向到/notallowed。
@active_required
/notallowed
更改顺序似乎可行,
@login_required @active_required def foo(request): ...
但我怀疑这种方法也有问题。
组合两个装饰器的正确方法是什么,为什么执行顺序与简单的Python装饰器不同?
现在,Python中的装饰器由内而外地工作
好吧,我想这取决于您由内而外的定义。对于您的情况,您要@login_required首先执行,因此它应该是“最外面的”(顶部)装饰器。
如您所述,您的最后一个示例有效,并且确实是实现此目的的正确方法。
编辑
困惑可能是这些特定装饰器的工作方式。
@login_required(@original_view) 返回一个新视图,该视图首先检查您是否已登录,然后调用original_view
@login_required(@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