Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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...

like image 925
d3m Avatar asked Dec 18 '12 11:12

d3m


People also ask

Can decorators have arguments?

The decorator arguments are accessible to the inner decorator through a closure, exactly like how the wrapped() inner function can access f . And since closures extend to all the levels of inner functions, arg is also accessible from within wrapped() if necessary.

How do decorators work in Flask?

Understanding Flask decoratorsA decorator is a function that takes in another function as a parameter and then returns a function. This is possible because Python gives functions special status. A function can be used as a parameter and a return value, while also being assigned to a variable.

Can you give a good use case for using a decorator in Python?

When to Use a Decorator in Python. You'll use a decorator when you need to change the behavior of a function without modifying the function itself. A few good examples are when you want to add logging, test performance, perform caching, verify permissions, and so on.


1 Answers

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
like image 90
Audrius Kažukauskas Avatar answered Oct 12 '22 21:10

Audrius Kažukauskas