Flask advanced stuff

Flashing (flash() call)

Display a temporary message on a page (cookies-based). Once page is refreshed, flash disappears, if not "triggered" again by the backend

from flask import flash
def index():
    flash()
{% for flash_msg in get_flashed_messages() %}
  <p style="color: red">{{flash_msg}}</p>
{% endfor %}

Forms (WTForms)

pip3 install flask-WTF
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import InputRequired, length, regexp

class MyForm(FlaskForm):
    username = StringField('User Name', validators=[InputRequired(), length(min=3), regexp("^aaaa$", message="must be aaaa")])
    #password = PasswordField('Your Password', validators=[InputRequired()])

    submit = SubmitField('Send!')
@app.route("/form", methods=['GET', 'POST'])
def index_form():
    form = MyForm()
    if form.validate_on_submit():  # valid, and POST request -> goes to this block
        return render_template_string("All good!")

    # invalid form (with input errors), or GET request
    return render_template("form.html", form=form)
<form method="POST" action="/form">
    {{ form.csrf_token }}

    {{ form.username.label }} {{ form.username(size=20) }}
    {% for error in form.username.errors %}
        <font color="red">{{ error }} </font>
    {% endfor %}


    {{ form.submit }}
</form>

For forms it's nice to use Bootstrap-Flask (older Flask-Bootstrap doesn't support newer Bootstrap4/5 versions)

To display the form in the middle of the page (vertically and horizontally), make sure HTML and BODY have "height=100%" style, and the form is defined something like this:

<div style="display: flex; height: 100%;
justify-content: center;
align-items: center;" class="container">
     <div style="display: inline-block" class="col-sm-4 col-sm-offset-4">
     FORM GOES HERE

(full flexbox tutorial).

The idea is that the outer div is a flexbox container, and it has its inner elements centered vertically (justify-content: center) and horizontally (align-items: center). Height of the container (and all upper containers) must be set to 100%.

So if we use Bootstrap-Flask, all we need to do in template is:

{% from 'bootstrap5/form.html' import render_form %}

<!DOCTYPE html>
<html lang="en" style="height: 100%;" >
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    {% block styles %}
            {{ bootstrap.load_css() }}
    {% endblock %}
</head>
<body style="height: 100%;">

<div style="width: 100%; height: 100%;" class="container">
    <div class="" style="display: flex; align-items: center; justify-content: center; height: 100%">
    <div style="" class="row col-sm-4 col-sm-offset-4">
        <form method="POST" action="/form" >
            {{ render_form(form) }}
        </form>
    </div>
    </div>
</div>

</body>
</html>

Admin (Flask-Admin)

from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView

admin = Admin(app, url="/admin")
admin.add_view(ModelView(MyDatabaseModelClass, db.session))

Custom views-templates must have the following contents

{% extends 'admin/master.html' %}
{% block body %}
    Hello World from MyView!
{% endblock %}

We can subclass ModelView and AdminIndexView, to embed login mechanism, like so:

class IndexView(AdminIndexView):
    @expose('/')
    def index(self):
        return self.render('admin_index.html')

    def is_accessible(self):
        return user.loggedin

    #def _handle_view(self, name, **kwargs):
        if not user.loggedin:
            return redirect("/loginpage")

Login (Flask-Login)

← Back to Articles