制作自定义 django 视图装饰器时遇到问题(带 args)
Posted
技术标签:
【中文标题】制作自定义 django 视图装饰器时遇到问题(带 args)【英文标题】:Having trouble making a custom django view decorator (with args) 【发布时间】:2013-11-26 17:14:51 【问题描述】:所以我已经阅读了所有类似的问题并复制了他们写的内容,但我仍然遇到问题。所以我想要这样的东西
# Yes, I know django has one but I want to make my own
@rate_limit(seconds=10)
myview(request, somearg, *args, **kwargs):
# Return a response
...
def rate_limit(seconds=10):
def decorator(view):
def wrapper(request, *args, **kwargs):
# Do some stuff
return view(request, *args, **kwargs)
return wrapper
return decorator
当我运行它时,我得到了错误
decorator() got an unexpected keyword argument 'somearg'
所以我附加装饰器来接收 args 和 kwargs 并得到这个错误
# New decorator signature
def decorator(view, *args, **kwargs)
和错误
'function' object has no attribute 'status_code'
编辑: 所以解决方案是使用。谢谢Martijn Pieters!
@rate_limit()
而不是
@rate_limit
【问题讨论】:
Hrm,这些错误似乎都没有意义。你确实想用functools.wraps()
装饰wrapper()
:from functools import wraps
,然后@wraps(view)
装饰def wrapper(...)
。
把def decorator(view):
改成def decorator(view, *args, **kwargs):
@karthikr:这不是问题。不可能,因为装饰器被传递只是函数到装饰。我强烈怀疑这不是 OP 运行的完整代码。
@karthikr:那是在解决错误的问题。我怀疑 OP 没有调用装饰器工厂。 @rate_limit
与 @rate_limit(10)
.
@karthikr:不,你不能。它是rate_limit()
是一个装饰器factory。它产生装饰器。 decorator()
是这里的实际装饰器。
【参考方案1】:
您的第一次尝试效果很好,但您可能忘记调用rate_limit()
装饰器工厂。
换句话说,如果你这样做,你的第一个错误就会发生:
@rate_limit
def myview(request, somearg, *args, **kwargs):
代替:
@rate_limit(seconds=10)
def myview(request, somearg, *args, **kwargs):
您还真的想在 Django 中使用的装饰器上使用 functools.wraps()
,特别是如果您想将它与其他 Django 装饰器(例如 csrf_exempt
)混合使用:
from functools import wraps
def rate_limit(seconds=10):
def decorator(view):
@wraps(view)
def wrapper(request, *args, **kwargs):
# Do some stuff
return view(request, *args, **kwargs)
return wrapper
return decorator
这可确保将要包装的函数上设置的任何属性正确复制到包装器。
【讨论】:
这成功了!我的意思是,在将 args 和 kwargs 添加到装饰器之后,将 () 添加到我的装饰器。为什么我必须像 @rate_limit() 那样调用它,而不是像其他装饰器那样调用 @rate_limit?或者如果需要参数,括号是否总是需要的? @JaredJoke:rate_limit()
是一个装饰器工厂。它生成实际的装饰器(它返回decorator
),让您根据参数构建不同的装饰器。 rate_limit(10)
返回一个装饰器,rate_limit(20)
返回另一个。 Python 然后使用返回的decorator
来实际装饰myview()
视图函数。
@JaredJoke: @some_expression
真的只是意味着:执行some_expression
,然后获取结果(必须是可调用的),并使用装饰函数调用它。所以rate_limit(10)
返回decorator
,称为传入myview
,而decorator
又返回wrapper()
,替换myview
函数。
django 如何让@login_required
和@login_required()
工作?...以上是关于制作自定义 django 视图装饰器时遇到问题(带 args)的主要内容,如果未能解决你的问题,请参考以下文章