为Flask装饰器添加参数

1 投票
1 回答
2201 浏览
提问于 2025-04-18 07:33

我在使用Flask的时候,有一段代码可以创建一个装饰器,用来处理HTTP基本认证:

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth.username, auth.password):
            return authenticate()
        return f(*args, **kwargs)
    return decorated

这个装饰器不允许传递参数。我想要修改它,让它可以传参数,请问我该怎么做呢?我查了其他关于装饰器的问题,但还是没能搞定。

1 个回答

8

使用装饰器时,紧接在函数(或类)定义前面的那一行必须是一个函数(或其他可调用对象),它的作用是接收一个函数(或类)并返回一个新的函数(或类)。

这意味着,如果你想给装饰器传递参数,那么下面这一行:

@requires_auth("admin")

必须是一个函数(或其他可调用对象)。换句话说,requires_auth("admin") 会被执行,执行的结果会用来装饰后面的函数(或类)。

也就是说,接受参数的那个函数必须返回一个真正进行装饰的函数!

比如这样:

def requires_auth(user):

    def decorator(f):
        # the actual decorator, which may use the variable "user"
        # (basically everything you've written, including the wrapper)

    return decorator

你也可以用类的形式来写。这个类的__init__方法会接受参数,而它的__call__方法会接受要被装饰的函数或类。也就是说,requires_auth("admin") 创建了一个对象的实例,然后这个实例会接收被装饰的函数,并完成装饰的工作。

class requires_auth:

    def __init__(self, user):
         self.user = user

    def __call__(self, f):
         # your decorator as above, referring to "self.user" for the arg

撰写回答