ust*_*tun 32 python django decorator
我试图通过两个装饰器来装饰Django视图,一个用于检查登录,另一个用于检查is_active.
第一个是内置的@login_required,第二个是以下内容:
def active_required(function):
dec = user_passes_test(lambda u: u.is_active, '/notallowed', '')
return dec(function)
Run Code Online (Sandbox Code Playgroud)
现在,Python中的装饰器内部工作,但以下不起作用:
@active_required
@login_required
def foo(request):
...
Run Code Online (Sandbox Code Playgroud)
我想首先检查用户是否已登录,如果没有,则重定向到登录页面,如果他或她已登录,我想检查他或她是否处于活动状态,如果没有,则执行重定向'/notallowed'.
如果login_required失败,用户不会被重定向到登录页面,而是@active_required被执行,并且由于用户在这种情况下为空,@ active_required装饰器失败并且用户被重定向到/notallowed.
改变顺序似乎有效,
@login_required
@active_required
def foo(request):
...
Run Code Online (Sandbox Code Playgroud)
但我怀疑这种方法也有问题.
组合两个装饰器的正确方法是什么,为什么执行顺序与简单的Python装饰器不同?
sec*_*ond 32
现在,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_vew
Run Code Online (Sandbox Code Playgroud)
dcr*_*sta 15
装饰器按它们在源中出现的顺序应用.因此,你的第二个例子:
@login_required
@active_required
def foo(request):
...
Run Code Online (Sandbox Code Playgroud)
相当于以下内容:
def foo(request):
...
foo = login_required(active_required(foo))
Run Code Online (Sandbox Code Playgroud)
因此,如果一个装饰器的代码依赖于由另一个装饰器设置(或由另一个装饰器确定),则必须将依赖装饰器"置于"depdended-on装饰器内部.
但是,正如Chris Pratt所说,你应该避免使用装饰器依赖; 必要时,创建一个新的装饰器,以正确的顺序调用它们.
Chr*_*att 12
如果装饰器具有真正独特的功能,那么它们才真正有意义.根据您的描述,您永远不会想要使用active_required但不会 使用login_required.因此,让login_and_active_required装饰器相应地检查两者和分支更有意义.少输入,少记录,否定问题.
为了进一步解释它(我一开始也感到困惑):active_required首先应用它是指它将它my_view封装在一些代码中。然后login_required应用,并将结果包装在更多代码中。
但是,当my_view实际调用此包装版本时,首先login_required执行by添加的代码(检查您是否已登录),然后active_required执行by by添加的代码(检查您是否处于活动状态),最后my_view执行。
| 归档时间: |
|
| 查看次数: |
13413 次 |
| 最近记录: |