Lekce 4 - Static files a upload souborů ve Flask
V minulé lekci, WTForms a Jinja2 šablony pro Flask framework, jsme si ukázali WTForms, "rozšíření" pro Flask, a vytvořili jsme si hlavní šablonu pomocí Jinja2.
V dnešním Python tutoriálu si ukážeme, jak používat statické soubory a nahrát soubor pomocí WTForms.
Static files
Nejdříve si stáhneme Bootstrap. Jedná se o populární CSS framework, díky kterému naší aplikaci vykouzlíme moderní vzhled téměř bez snažení. Bootstrap navíc umožňuje velmi jednoduše podporovat zobrazení stránek i na mobilních zařízeních. Více informací případně naleznete v našem kurzu Bootstrap.
Vytvoříme složku root/static/
, kde root/
je
složka s vaší aplikací, a celou složku Bootstrap tam přesuneme.
Pro ukázku si vytvoříme následující skript
root/static/main.js
, který také načteme:
alert("Po odkliknutí se stránka načte")
Do hlavní šablony linkneme do části
<head>...</head>
skript main.js
a
minifikovaný Bootstrap CSS soubor:
</style> <script src="{{ url_for('static', filename = 'main.js') }}"></script> <link rel="stylesheet" href="{{ url_for('static', filename='bootstrap-4.1.3-dist/css/bootstrap.min.css')}}"> </head>
Stránka nyní načítá skript a Bootstrap.
Jelikož máme Bootstrap, vylepšíme vzhled našeho formuláře.
Jednotlivým polím přidáme Bootstrap třídy a namísto
<input type="submit">
si vytvoříme submit tlačítko
pomocí WTForms, rovněž s Bootstrap CSS třídami, které jej ostylují:
class MujFormular(FlaskForm): prvni_cislo = IntegerField("První Číslo", widget = widgets.Input(input_type = "number"), render_kw = dict(class_ = "form-control")) operator = SelectField("Operátor", choices=[("+" ,"+"), ("-", "-"), ("*", "*"), ("/", "/")], render_kw = dict(class_ = "form-control")) druhe_cislo = IntegerField("Druhé Číslo", widget = widgets.Input(input_type = "number"), render_kw = dict(class_ = "form-control")) submit = SubmitField("Odeslat", render_kw = dict(class_ = "btn btn-outline-primary btn-block"))
Všimněte si, že jsme přidali parametr render_kw
pomocí
kterého můžeme přidat vygenerovanému kódů například třídu, hodnotu a
další atributy.
Upravíme i šablonu:
{% extends "base.html" %} {% block header %} Zde je něco zajímavého<br> {{ super() }} {% endblock %} {% block content %} <form method="POST" class="row justify-content-center"> {{ 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>{{ form.submit.label }}</td><td> {{ form.submit }}<td></tr> </table> </form> <div class="text-center"> {% 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> </div> {% endblock %}
Aplikace nyní vypadá mnohem lépe
Upload souborů
Pro ukázku si vytvoříme další stránku, která bude fungovat jako
galerie obrázků s možností nahrát vlastní obrázky. Do
main.py
přidáme importy a novou metodu:
from wtforms import FileField from flask_wtf.file import FileRequired from werkzeug.utils import secure_filename import os #Nastavíme složku, kam se budou obrázky ukládat UPLOAD_FOLDER = app.static_folder + "/uploads/" app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER class FileFormular(FlaskForm): soubor = FileField("Vlož obrázek", validators = [FileRequired()]) submit = SubmitField("Odeslat", render_kw = dict(class_ = "btn btn-outline-primary btn-block")) @app.route("/galerie/", methods = ["GET", "POST"]) def galerie(): form = FileFormular() if form.validate_on_submit(): soubor = form.soubor.data nazev = secure_filename(soubor.filename) soubor.save(os.path.join(app.config['UPLOAD_FOLDER'], nazev)) return render_template("galerie.html", form = form)
Nejdříve nastavíme složku, kam se budou obrázky ukládat (v tomto
případě root/static/uploads
, proto jsme použili
app.static_folder
). Vytvoříme si formulář s file inputem
(použijeme validátor FileRequired()
pro validaci, zda byl soubor
přiložen) a submit tlačítkem.
Nakonec přidáme logiku samotné stránky. Ze všeho nejdříve se provede
validace formuláře, pak si vezmeme obrázek a zkontrolujeme pomocí nástroje
z knihovny werkzeug
, na které mimochodem běží Flask, zda je
název souboru bezpečný, a soubor uložíme.
Také si musíme vytvořit novou šablonu, která se bude nacházet v
root/templates/galerie.html
:
{% extends "base.html" %} {% block header %} Galerie {% endblock %} {% block content %} <form method="POST" class="row justify-content-center" enctype="multipart/form-data"> {{ form.hidden_tag() }} <table> <tr><td>{{ form.soubor.label }}:</td><td>{{ form.soubor }}</td></tr> <tr><td>{{ form.submit.label }}</td><td> {{ form.submit }}<td></tr> </table> </form> <div class="text-center"> {% 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> </div> {% endblock %}
Zkusíme si nahrát obrázek pandy, aplikace se nachází na
http://127.0.0.1:5000/galerie/
.
Výtečně, obrázek se úspěšně nahrál
Teď již jen potřebujeme získat všechny obrázky ze složky a zobrazit je na stránce:
@app.route("/galerie/", methods = ["GET", "POST"]) def galerie(): form = FileFormular() if form.validate_on_submit(): soubor = form.soubor.data nazev = secure_filename(soubor.filename) soubor.save(os.path.join(app.config['UPLOAD_FOLDER'], nazev)) obrazky = os.listdir(app.static_folder + "/uploads") return render_template("galerie.html", form = form, obrazky = obrazky)
Použijeme funkci os.listdir
, která vrací pole souborů
nacházejících se ve složce. Stačí je zobrazit v šabloně:
{% extends "base.html" %} {% block header %} Galerie {% endblock %} {% block content %} <form method="POST" class="row justify-content-center" enctype="multipart/form-data"> {{ form.hidden_tag() }} <table> <tr><td>{{ form.soubor.label }}:</td><td>{{ form.soubor }}</td></tr> <tr><td>{{ form.submit.label }}</td><td> {{ form.submit }}<td></tr> </table> </form> <div class="text-center"> {% 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> </div> {% for obrazek in obrazky %} <img src="{{ url_for('static', filename='uploads/' + obrazek) }}"> {% endfor %} {% endblock %}
Výsledná galerie vypadá takto:
V příští lekci, Přihlášení uživatelů ve Flask, se naučíme přihlásit uživatele do naší webové aplikace ve Flask.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 129x (657.55 kB)
Aplikace je včetně zdrojových kódů v jazyce Python