Flask flash message on all endpoints



In my Flask app I have user management done via flask.session. So all info about logged in user is stored in session. When some new user registers, in database I create new row with one attribute being verified set to false and the same information is stored in session['user']['verified']. When user browses the website, no matter which endpoint, I want to flash him a message, that he still did not verify his email address.

So far I managed to do this by creating @after_request method like so:

@app.after_request
def check_user_verification_status(response):
    try:
        if not session['user']['verified']:
            flash("Your email address is still not verified, ...")
    except Exception:
        pass
    return response

This way the flash message really appears on all endpoints, but sometimes it appears duplicated because of some redirects being made. I solved the duplication problem following this answer: Flask – duplicates flash messages

But when I am on main page and click on logout button, which redirects to endpoint logout (the endpoint logs out user – deletes user info from session – and redirects to main page), the flash message about not verified user also appears, even when no user is then technically logged in, because of finished original request, which was processed just before the redirect to logout endpoint and there was still user info in session.

Is there some solution to this problem. Something like “After request for all endpoints which will be called only once after all redirects” so it flashes the message just once (or zero times when the condition is not met)?

Answer

At the end I solved current problem by editing of my layout.html page.

Every Jinja template in my app uses layout so the solution was to use simple Jinja if statement, which asked for verified variable. If it is true, it just shows div with message informing user, that email address is not verified. I added to the div the same class as classic flash messages have and this way it looks exactly the same as flash message.

{% if not verified %}
  <div class="msg info">Your email address is still not verified, ...</div>
{% endif %}

And the verified variable is always refreshed in @before_request method and set to g.verified (global variable – flask.g). This is then passed to every Jinja template (every endpoint) by overriding render_template() method as follows:

import flask
from flask import g

@app.before_request
def set_user_info():
    g.verified = is_user_verified()

def render_template(template, **kwargs):
    return flask.render_template(template, verified=g.config, **kwargs)

It may not be the best solution, but I like it a bit more than solution mentioned in comment below the question.



Source: stackoverflow