I have a blueprint and some url functions,
admin_bp = Blueprint('admin', __name__)
@admin_bp.route('/dashboard', methods=['GET', ])
@flask_login.login_required
def dashboard():
context = {}
page = 'admin/dashboard.html'
return render_template(page, **context)
@admin_bp.route('/deny', methods=['GET', ])
@flask_login.login_required
def deny():
return 'hey bro you dont belong here'
I don't want to copy paste @flask_login.login_required
decorator for all url functions under this blueprint. Is there a better way that I can apply decorator for all blueprint urls?
You can add before_request()
as a function that will run before each request in a view.
You will then want to add decorators to inject additional functionality to the before_request
function. You will want to import the login_required
decorator to ensure each endpoint requires a logged in user. This decorator is part of the flask_login
library.
Since it looks like your views are part of an admin, I'd also recommend adding a custom decorator to your before_request
function with something like @role_required('admin')
. The functionality for that decorator will live somewhere else and be imported.
@admin_bp.before_request
@login_required
def before_request():
""" Protect all of the admin endpoints. """
pass
Subclass Blueprint
and override the route
method.
import flask
class MyBlueprint(flask.Blueprint):
def route(self, rule, **options):
def decorator(f):
# these lines are copied from flask.Blueprint.route
endpoint = options.pop("endpoint", f.__name__)
self.add_url_rule(rule, endpoint, f, **options)
# At this point flask.Blueprint.route simply returns f.
# But you can nest a decorator.
def inner(*args, **kwargs):
# stuff you want to do before each request goes here
try:
result = f(*args, **kwargs)
# stuff you want to do on successful responses (probing status, headers, etc.) goes here
except Exception as e:
# stuff you want to do on error responses goes here
raise
return inner
Now use the new subclass in your blueprints:
-v1_blueprint = Blueprint('v1', __name__)
+v1_blueprint = MyBlueprint('v1', __name__)
No changes needed to individual routes.
The drawback of this approach is that it copies code from inside Flask. If the implementation of flask.Blueprint.route
were to change in a future version, you'd need to sync MyBlueprint with it when you upgrade Flask.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With