Vánoční nadílka Vánoční nadílka
Vánoční akce! Daruj lepší budoucnost blízkým nebo sobě. Až +50 % zdarma na dárkové poukazy. Více informací

Lekce 3 - WTForms a Jinja2 šablony pro Flask framework

Python Flask WTForms a Jinja2 šablony pro Flask framework

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Seznámení s Flask microframeworkem, jsme si vytvořili aplikaci Kalkulačka, abychom si ukázali, jak fungují formuláře a jak z nich získat data. V dnešním Python tutoriálu si ukážeme, jak vytvořit formulář ještě lépe pomocí knihovny WTForms. Ty podporují např. automatické validace na straně serveru nebo ochranu proti CSRF útoku. To jsou poměrně základní funkce, které od formulářů u aplikací požadujeme, a proto budeme knihovnu i nadále používat.

WTForms

Abychom si mohli vůbec nějaký ten formulář vytvořit, musíme si toto "rozšíření" nainstalovat pomocí nástroje pip:

py -m pip install flask-wtf

Pokud instalace WTForms proběhla úspěšně, uvidíte výstup podobný tomuto:

C:\Users\David>py -m pip install flask-wtf
Collecting flask-wtf
  Downloading https://files.pythonhosted.org/packages/60/3a/58c629472d10539ae516
7dc7c1fecfa95dd7d0b7864623931e3776438a24/Flask_WTF-0.14.2-py2.py3-none-any.whl
Requirement already satisfied: Flask in c:\users\david\appdata\local\programs\py
thon\python36-32\lib\site-packages (from flask-wtf)
Collecting WTForms (from flask-wtf)
  Downloading https://files.pythonhosted.org/packages/9f/c8/dac5dce9908df1d9d48e
c0e26e2a250839fa36ea2c602cc4f85ccfeb5c65/WTForms-2.2.1-py2.py3-none-any.whl (166
kB)
    100% |████████████████████████████████| 174kB 2.2MB/s
Requirement already satisfied: Jinja2>=2.10 in c:\users\david\appdata\local\prog
rams\python\python36-32\lib\site-packages (from Flask->flask-wtf)
Requirement already satisfied: click>=5.1 in c:\users\david\appdata\local\progra
ms\python\python36-32\lib\site-packages (from Flask->flask-wtf)
Requirement already satisfied: Werkzeug>=0.14 in c:\users\david\appdata\local\pr
ograms\python\python36-32\lib\site-packages (from Flask->flask-wtf)
Requirement already satisfied: itsdangerous>=0.24 in c:\users\david\appdata\loca
l\programs\python\python36-32\lib\site-packages (from Flask->flask-wtf)
Requirement already satisfied: MarkupSafe>=0.23 in c:\users\david\appdata\local\
programs\python\python36-32\lib\site-packages (from Jinja2>=2.10->Flask->flask-w
tf)
Installing collected packages: WTForms, flask-wtf
Successfully installed WTForms-2.2.1 flask-wtf-0.14.2

C:\Users\David>

Použijeme aplikaci z minulé lekce s tím rozdílem, že formulář vytvoříme pomocí WTForms:

# Importujeme
from flask_wtf import FlaskForm
from wtforms import SelectField, IntegerField, widgets

app = Flask(__name__)
# Musíme nastavit SECRET_KEY, pokud chceme používat CSRF
app.config["SECRET_KEY"] = "super tajny klic"

class MujFormular(FlaskForm):
    prvni_cislo = IntegerField("První Číslo", widget = widgets.Input(input_type = "number"))
    operator = SelectField("Operátor", choices=[("+" ,"+"), ("-", "-"), ("*", "*"), ("/", "/")])
    druhe_cislo = IntegerField("Druhé Číslo", widget = widgets.Input(input_type = "number"))

@app.route("/", methods = ["GET", "POST"])
def kalkulacka():
    form = MujFormular()
    if form.validate_on_submit():
        prvni_cislo = form.prvni_cislo.data
        druhe_cislo = form.druhe_cislo.data
        operator = form.operator.data
        vysledek = eval( str(prvni_cislo) + operator + str(druhe_cislo) )
        return render_template("template.html", vysledek = vysledek, form = form)
    return render_template("template.html", form = form)

Nejprve si vytvoříme třídu MujFormular, poté vytvoříme 3 políčka. U políček je prvním parametrem popisek, který můžeme zobrazit pomocí Jinja2 šablon. Dále nastavíme inputům s číslem widget s typem number (stejné jako napsat <input type="number">) a SelectField má jako další argument pole, které obsahuje dvojice value a text, které se zobrazí na stránce k výběru. Všimněte si rozšíření konfigurace aplikace o ochranu proti podvrhnutí formuláře přes útok CSRF.

Následně si vytvoříme instanci formuláře, který si automaticky vezme data z requestu. Poté zkontrolujeme, zda byl formulář odeslán a provedeme validaci dat. Pokud vše proběhlo úspěšně, data načteme a vrátíme výsledek.

Upravíme náš template a přidáme vygenerovaný formulář.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <form method="POST">
        {{ form.hidden_tag() }}
        {{ form.prvni_cislo }}
        {{ form.operator }}
        {{ form.druhe_cislo }}
        <input type="submit">
    </form>
    <hr>
    Výsledek: {% if vysledek %} {{ vysledek }} {% else %} Vyplň formulář {% endif %}
</body>
</html>

Nejdříve vykreslíme všechny skryté tagy. Jelikož žádné nemáme, načte se pouze CSRF token, který našemu formuláři poskytuje ochranu proti podvržení. Poté načteme ostatní vstupní pole.

Aktuálně se nám budou ověřovat pouze číselná pole, pokud obsahují číslo, a pole s operátorem, zda obsahuje jeden ze znaků /*-+. To nám nestačí a chceme vypsat i chybovou hlášku ke každému inputu. Kód tedy ještě upravíme:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <form method="POST">
        {{ form.hidden_tag() }}
        {{ form.prvni_cislo }}
        {{ form.operator }}
        {{ form.druhe_cislo }}
        <input type="submit">
    </form>
    {% for field, errors in form.errors.items() %}
        {% for error in errors %}
            <span style="color: red;">Chyba pole - {{ field }} hláška - {{ error }}</span><br>
        {% endfor %}
    {% endfor %}
    <hr>
    Výsledek: {% if vysledek %} {{ vysledek }} {% else %} Vyplň formulář {% endif %}
</body>
</html>

Chybová hláška vypadá takto:

Chybová hláška při validaci formulářů ve WTForms ve Flask frameworku v Pythonu

Tvorba hlavní šablony

Bývá zvykem, že webová aplikace má nějakou hlavní šablonu (rozložení s navigačním menu, hlavičkou, patičkou a pozadím) a jednotlivé podstránky se poté vykreslují dovnitř. Pojďme tak učinit i u kalkulačky.

Nejprve si vytvoříme šablonu stránky. Pro náš účel stačí něco jednoduchého, klidně si motiv poté upravte dle libosti. Vytvoříme si šablonu base.html, kterou vložíme do složky root/templates/. Kód bude mít následující:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Můj web ve Flasku</title>
    <style>
        html, body{
            margin: 0;
        }
        #content{
            margin: auto;
            max-width: 75%;
            min-height: 500%;
            border: solid;
            border-color: black;
            border-width: 2px;
            border-radius: 15px;
            padding: 100px;
            font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
        }
        header{
            min-height: 100px;
            min-width: 100%;
            background-color: #569ee2;
            margin-bottom: 50px;
            font-family: Arial Black;
        }
        footer{
            position: absolute;
            bottom: 0;
            min-height: 120px;
            min-width: 100%;
            background-color: #569ee2;
            font-family: Arial Black;
        }
    </style>
</head>
<body>
    <header>
        {% block header %}
        Zde není nic zajímavého
        {% endblock %}
    </header>
    <div id="content">
        {% block content %}
        {% endblock %}
    </div>
    <footer>
        {% block footer %}
        Prostý footer
        {% endblock %}
    </footer>
</body>
</html>

Všimněte si, že jsme si zde definovali bloky header, content a footer a do bloků header a footer jsme vložili nějaký text. Ten se zobrazí na stránce dědící z této šablony (tedy podstránce) pouze pokud blok nepoužijeme nebo Jinja2 donutíme vyrenderovat obsah pomocí {{ super() }}.

Vše je vidět z následující úpravy template.html, který nyní dědí z tohoto hlavního a vykresluje se tedy do něj. Obsahuje již jen HTML kód potřebný pro danou podstránku s kalkulačkou a je kratší:

{% extends "base.html" %}
{% block header %}
Zde je něco zajímavého<br>
{{ super() }}
{% endblock %}

{% block content %}
    <form method="POST">
        {{ form.hidden_tag() }}
        <table>
            <tr><td>{{ form.prvni_cislo.label }}:</td><td>{{ form.prvni_cislo }}</td></tr>
            <tr><td>{{ form.operator.label }}: </td><td>{{ form.operator }}</td></tr>
            <tr><td>{{ form.druhe_cislo.label }}: </td><td>{{ form.druhe_cislo }}</td></tr>
            <tr><td></td><td><input type="submit" style="width: 100%;"></td></tr>
        </table>
    </form>
    {% for field, errors in form.errors.items() %}
        {% for error in errors %}
            <span style="color: red;">Chyba pole - {{ field }} hláška - {{ error }}</span><br>
        {% endfor %}
    {% endfor %}
    <hr>
    Výsledek: {% if vysledek %} {{ vysledek }} {% else %} Vyplň formulář {% endif %}
{% endblock %}

Výsledek vypadá následovně, všimněte si headeru a footeru:

V příští lekci, Static files a upload souborů ve Flask, se podíváme na statické soubory a nahrávání.


 

Stáhnout

Staženo 4x (1.75 kB)
Aplikace je včetně zdrojových kódů v jazyce Python

 

 

Článek pro vás napsal MQ .
Avatar
Jak se ti líbí článek?
1 hlasů
Autor je srdcem Pythonista.
Miniatura
Všechny články v sekci
Flask framework pro Python
Miniatura
Následující článek
Static files a upload souborů ve Flask
Aktivity (2)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!