3

所以我已经阅读了所有类似的问题并复制了他们写的内容,但我仍然遇到问题。所以我想要这样的东西

# 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'

编辑: 所以解决方案是使用。谢谢马丁彼得斯!_

@rate_limit()

代替

@rate_limit
4

1 回答 1

10

您的第一次尝试效果很好,但您可能忘记调用装饰rate_limit()器工厂。

换句话说,如果你这样做,你的第一个错误就会发生:

@rate_limit
def myview(request, somearg, *args, **kwargs):

代替:

@rate_limit(seconds=10)
def myview(request, somearg, *args, **kwargs):

您还真的想functools.wraps()在 Django 中使用的装饰器上使用,特别是如果您想将它与其他 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

这可确保将要包装的函数上设置的任何属性正确复制到包装器。

于 2013-11-13T21:54:02.727 回答