Ep. 28 uWSGI Decorators
16 Apr 2019
Custom Flask decorators | Learning Flask Ep. 28
Using Python decorators to add another layer of functionality to Flask routes
Just like decorators in Python allow us to add additional functionality to functions. View decorators in Flask allow us to add additional functionality to routes.
As a view (or route) in Flask is a Python function, we can implement our own decorators to add another layer of functionality to them.
Python decorators
Here's an example of a basic Python decorator:
Running the above prints:
Pay attention to the order of execution.
The first call to
print()
was from within our decoratorFollowed by the 2 calls to
print()
inmy_function
You'll also notice, the decorator changed the values we passed into the my_function
call.
By decorating a function with @my_decorator
, the function directly below it is passed into the my_decorator
code as the function
agument.
The original my_function
is replaced with the function
we returned in our decorator.
You'll also notice we've imported wraps
from functools
.
@wraps
is not required, but helps us by copying the function docsting, name, attributes etc. from the original function to the copy of the function inside the decorator!
Here's another example that accepts arguments in the decorator:
running this prints:
Flask decorators
If you've used Flask before, you'll be very familiar with many of Flask's decorators, such as:
@app.route
Use the @app.route
decorator to define the routes in your application:
@app.before_request
Use the @app.before_request
decorator to trigger a function to run before every request:
@app.errorhandler(err_code)
Use the @app.errorhandler
decorator to catch errors:
As you can see, decorators are ubiquitous in Flask!
Custom Flask decorators
Armed with the knowledge to write your own custom decorators, here's an example:
Let's step through each line of our decorator:
Here we define a function, which will be the name of our decorator. The f
argument is the function which we'll decorate.
We'll use the @wraps
decorator and pass it the function (f
), copying the original function f
's metadata to the new function we're about to define.
The name of this function doesn't matter, however it's used to modify the behaviour and values passed into the original function.
Here, we're checking the g.user
has a True
value for the superuser
attribute. If not, we're calling abort(404)
.
Returns the newly modified function and any arguments passed into it. You'll notice that we haven't modified any of the *args
or **kwargs
passed into the function, but we still need to return them.
This line just returns the new function to the parent function so it can be returned.
Using the decorator
Now that we have our decorator, we can use it:
Decorators can be stacked, and you'll notice we've used our @superuser
just under the @app.route
decorator.
Any time a request is sent to this route, it will trigger the @superuser
decorator to run. If someone tried to access the /users
URL and doesn't have the right permissions defined in our decorator, the request will be aborted.
Decorator arguments
Sometimes, it's useful to pass arguments into our custom decorators:
We now have access to the access_level
value passed into our decorator.
Usage:
This can be useful for reusing a decorator and passing it different values for different functionality:
You may want to decorate views, passing in different values to the decoartor and letting it handle the validation:
Wrapping up
Decorators in Flask are a great way to add an additional layer of functionality to a route and provide a nice way to keep your code DRY.
Last modified · 16 Apr 2019 Reference : https://pythonise.com/series/learning-flask/custom-flask-decorators
Last updated