制作自定义django视图装饰器时遇到问题(使用args)

Jar*_*oke 3 python django decorator python-decorators

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

# 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
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我得到了错误

decorator() got an unexpected keyword argument 'somearg'
Run Code Online (Sandbox Code Playgroud)

所以我追加装饰器来接受args和kwargs并得到这个错误

# New decorator signature
def decorator(view, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

和错误

'function' object has no attribute 'status_code'
Run Code Online (Sandbox Code Playgroud)

编辑: 所以解决方案是使用.谢谢Martijn Pieters!

@rate_limit()
Run Code Online (Sandbox Code Playgroud)

代替

@rate_limit
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 8

你的第一次尝试工作得很好,但你可能忘了打电话rate_limit()装饰工厂.

换句话说,如果您执行此操作,则会出现第一个错误:

@rate_limit
def myview(request, somearg, *args, **kwargs):
Run Code Online (Sandbox Code Playgroud)

代替:

@rate_limit(seconds=10)
def myview(request, somearg, *args, **kwargs):
Run Code Online (Sandbox Code Playgroud)

你也真的想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
Run Code Online (Sandbox Code Playgroud)

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