python两个装饰器执行顺序_关于python:Django中有多个装饰器用于视图:执行顺序...

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

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

1

2

3def active_required(function):

dec = user_passes_test(lambda u: u.is_active, '/notallowed', '')

return dec(function)

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

1

2

3

4@active_required

@login_required

def foo(request):

...

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

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

更改顺序似乎可行,

1

2

3

4@login_required

@active_required

def foo(request):

...

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

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

Now, the decorators in Python work inside out

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

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

编辑

也许混淆是(这些特定的)装饰器的工作方式

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

所以

1

2

3

4

5

6

7

8

9login_required(

active_required(

my_view

)

)

first checks if you are logged in, then

first(second) checks if you are active, then

runs my_vew

嗯,我对订单还是有些困惑:stackoverflow.com/a/739665/72436和stackoverflow.com/a/8715839/72436提出了其他建议。

好的,我想您已将其钉牢,区别在于返回一个函数与调用它。

装饰器按照它们在源中出现的顺序应用。因此,您的第二个示例:

1

2

3

4@login_required

@active_required

def foo(request):

...

等效于以下内容:

1

2

3def foo(request):

...

foo = login_required(active_required(foo))

因此,如果一个装饰器的代码依赖于由另一个装饰器设置(或由另一个装饰器确保),则必须将从属装饰器"放在"依赖的装饰器中。

但是,正如克里斯·普拉特(Chris Pratt)所指出的那样,您应该避免具有装饰器依赖性。必要时,创建一个新的装饰器,以正确的顺序调用两者。

好的,但是我只想反过来:首先,应应用login_required,然后再应用active_required。所以,不应该像我给的第一个例子一样吗?

在这种情况下,首先应用login_required -一种思考方式是对foo的调用首先通过login_required返回的函数,然后通过active_required返回的函数。您可以使用PDB单步执行,也可以添加调试print来了解我的意思。

仅当堆栈装饰器具有真正独特的功能时,它才有意义。根据您的描述,永远不会出现要使用active_required而不是login_required的情况。因此,拥有一个login_and_active_required装饰器来同时检查和检查分支更有意义。更少的打字,更少的文档,并消除了问题。

好的,我想Django的内置函数要比自定义代码更可靠。 Django没有这个装饰器有点奇怪,但是它应该很常见。我已经看到一些标记为WONTFIX的错误报告。

同意由于is_active是内置的,并且在大多数情况下几乎是login_required的取反,因此开发人员应该立即解决这个问题,但要谨慎。

为了进一步解释它(我一开始也感到困惑):首先应用active_required表示它接受my_view并将其包装在某些代码中。然后应用login_required并将结果包装在更多代码中。

但是,当实际调用此包装的my_view版本时,首先执行由login_required添加的代码(检查您是否已登录),然后执行由active_required添加的代码(检查您是否处于活动状态) ),最后执行my_view。

这是一种很好的区分差异的好方法,以清除此处的注释:stackoverflow.com/a/8715821/781695

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值