Search code examples
pythondecoratorflask

How can a Flask decorator have arguments?


I implemented a decorator in the same way as here How to make a python decorator function in Flask with arguments (for authorization) but problem still unsolved...

I have this function with decorators

@blueprint.route('<var>')
@blueprint.my_decorator(var)
def function(var):
    do stuff

and I get this error

NameError: global name 'var' is not defined

How do I solve this?


Update

The blueprint is a class inheriting the Blueprint class. So I implemented the method

def my_decorator(self, fn):
    @wraps(fn)
    def decorator(*args, **kwargs):
        value = kwargs['value']
        # do stuff with value
        return fn(*args, **kwargs)
    return decorator

but still the value is an uknown key...


Solution

  • Decorators are executed at import time, they're essentially syntactic sugar:

    @foo(bar)
    def baz():
        return 'w00t!'
    

    is equivalent to

    def baz():
       return 'w00t!'
    baz = foo(bar)(baz)
    

    So in the example above variable bar must exist in the global scope of this module before it is passed to the decorator as argument. That's what the error you've got tells you.


    Update

    Based on the discussion below, the code in the question should intercept the value passed to view function and do something with it. Here's an example that demonstrates it:

    from functools import wraps
    from flask import Flask, abort
    
    app = Flask(__name__)
    
    def foobar(fn):
        @wraps(fn)
        def decorated_view(*args, **kwargs):
            value = kwargs['value']
            # Do something with value...
            if value == 'foobar':
                abort(400)
            return fn(*args, **kwargs)
        return decorated_view
    
    @app.route('/<value>')
    @foobar
    def view(value):
        return value