John Bergson
John Bergson

Reputation: 435

python flask do something at each route

I have a flask app where I have to delete and update user information, like this (simplified):

@app.route('/<user>')
def show_user(user):
    """ Show user information """
    render_template('show_user.html')

@app.route('/delete/<user>')
def delete_user(user):
    """ Delete user from database """
    delete_user_from_db(user)
    return redirect(url_for('show_users', user=user)

@app.route('/update/<user>', method=["POST"])
def update_user(user):
    """ Update user information """
    update(user, stuff_from_POST)
    return redirect(url_for('show_users', user=user)

For each of these methods I need to verify whether the user specified in the URL is really a valid user, so I'd do something like this at the beginning of all those functions:

if user not in mydb:
    do(something)
    abort(404)

This is rather cumbersome, and since I will be having more functions that depend on the user to be valid, I was wondering if it were possible to wrap that block in another function that gets automatically executed when those routes are called.

Thanks in advance.

Upvotes: 4

Views: 2724

Answers (1)

Paul Rooney
Paul Rooney

Reputation: 21609

Use the before_request hook function see docs

@app.before_request
def before_request():
    if user not in mydb:
    do(something)
    abort(404)

Edit:

I tried this

from flask import Flask, request
app = Flask(__name__)

db = ['paul', 'steve', 'anna']

@app.before_request
def before_request():
    if request.endpoint in ['show_user', 'delete_user', 'update_user']:
        user = request.path[request.path.rfind('/') + 1:]
        if user not in db:
            return 'user not found', 404

@app.route('/<user>')
def show_user(user):
    """ Show user information """
    return 'hello %s' % user

@app.route('/other')
def show_other():
    """ Demonstrates other routes are not effected by before_request """
    return 'other stuff'

if __name__ == "__main__":
    app.run()

It's not actually as neat as I hoped but it works.

It's a little unfortunate to have to maintain which endpoints do what in the before_request function. If you were doing REST you might be able to merge these endpoints into one and simply use different http methods for each action.

Upvotes: 7

Related Questions