Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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.

Bootstrap a alert skript pro Flask framework pro Python - Flask framework pro Python

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 :)

Webová aplikace s frameworky Bootstrap a Flask v Pythonu - Flask framework pro Python

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/.

Upload obrázků v microframeworku Flask v Pythonu - Flask framework pro Python

Výtečně, obrázek se úspěšně nahrál :)

Nahraný obrázek v microframeworku Flask v Pythonu - Flask framework pro Python

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:

Galerie obrázků ve Flask frameworku v Pythonu - Flask framework pro Python

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 114x (657.55 kB)
Aplikace je včetně zdrojových kódů v jazyce Python

 

Předchozí článek
WTForms a Jinja2 šablony pro Flask framework
Všechny články v sekci
Flask framework pro Python
Přeskočit článek
(nedoporučujeme)
Přihlášení uživatelů ve Flask
Článek pro vás napsal MQ .
Avatar
Uživatelské hodnocení:
28 hlasů
Používám hlavně Python a zajímám se o Deep Learning a vše kolem.
Aktivity