5. diel - Prihlásenie užívateľov vo Flask
V minulej lekcii, Static files a upload súborov vo Flask , sme si ukázali, ako používať static files a nahrávať súbory do galérie. V dnešnom Python tutoriále si ukážeme, ako za použitia Flask frameworku vytvoriť prihlasovací formulár, používať session a aplikáciu si rozdelíme na jednotlivé moduly pomocou Blueprint, pretože písať celú aplikáciu do jediného súboru nie je efektívne.
Prihlasovací formulár
Zo všetkého najskôr potrebujeme formulár, ktorý vytvoríme pomocou
WTForms. Stále pokračujeme s našou učebné aplikácií, do
main.py
pridáme ďalšie importy a triedu reprezentujúci
prihlasovací formulár:
from wtforms import StringField, PasswordField from wtforms.validators import InputRequired class LoginForm(FlaskForm): user = StringField("Uživatel", validators = [InputRequired()], render_kw = dict(class_ = "form-control")) #Přihlašovací jméno password = PasswordField("Heslo", validators = [InputRequired()], render_kw = dict(class_ = "form-control")) #Heslo submit = SubmitField("Odeslat", render_kw = dict(class_ = "btn btn-outline-primary btn-block"))
Vytvárame 2 vstupné pole na užívateľské meno a heslo (+ submit
tlačidlo). Aplikujeme validátor InputRequired()
, keďže chceme,
aby užívateľ musel obe polia vyplniť.
Teraz vytvoríme logiku stránky, ktorá sa bude nachádzať na adrese
http://127.0.0.1:5000/login/
. Opäť pokračujeme v
main.py
:
from flask import session @app.route("/login/", methods = ["GET", "POST"]) def login(): form = LoginForm() if form.validate_on_submit(): user = form.user.data password = form.password.data if password == "letmein": session["user"] = user return render_template("login.html", form = form)
Najskôr si importujeme session
. Slovensky sa často používa
preklad "relácie" a práve tento mechanizmus nám umožňuje zapamätať si,
že je daný užívateľ prihlásený. Vnútorne sessions fungujú pomocou
cookies v prehliadači používateľa a ďalšieho mechanizmu na serveri, ktorý
tieto cookies overuje. Zadané údaje sme si do session
uložili
pod kľúč "user"
.
Ako vždy si vytvárame inštanciu formuláre, vykonáme validáciu a získame dáta. Potom kontrolujeme, či je heslo "letmein" a do session uložíme meno používateľa. Zatiaľ užívateľa neukladáme do databázy, ale máme jedno heslo pre všetkých. Ďalej v kurze aplikácii ešte vylepšíme.
Keďže sa poriadny web nezaobíde bez stránky pre odhlásenie
užívateľov, vytvoríme si tiež jednu. Stránka pre odhlásenie sa bude
nachádzať na adrese http://127.0.0.1:5000/logout/
. Pridáme teda
ďalší route a metódu do main.py
:
from flask import redirect, url_for @app.route("/logout/", methods = ["GET", "POST"]) def odhlasit(): session.pop("user", None) return redirect(url_for("login"))
Keďže session
funguje rovnako ako dictionary
čiže slovník, tak pomocou funkcie session.pop(klíč, hodnota)
našej session
s kľúčom "user"
odstránime.
Nakoniec užívateľa presmerujeme na stránku s loginom. Druhý parameter
funkciu odovzdávame, aby nám v prípade neexistujúceho kľúča nevyvolala
error.
Toto je error, ktorý by na nás vyskočil, bez druhého parametru vo funkcii
session.pop()
:
Vytvoríme si šablónu pre stránku s prihlasovacím formulárom
root/templates/login.html
:
{% extends "base.html" %} {% block header %} {{ super() }} <!-- V hlavní šabloně se bude vypisovat aktuální uživatel, proto vyrenderujeme její header --> {% endblock %} {% block content %} <form method="POST" class="row justify-content-center"> {{ form.hidden_tag() }} <table> <tr><td>{{ form.user.label }}:</td><td>{{ form.user }}</td></tr> <tr><td>{{ form.password.label }}: </td><td>{{ form.password }}</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 %}
Upravíme si hlavnú šablónu base.html
, u ktorej odstránime
skript root/static/main.js
(ten môžete zmazať) a v header budeme
vypisovať aktuálneho užívateľa:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Můj web ve Flasku</title> <style> <!-- Styl zůstává stejný --> </style> <link rel="stylesheet" href="{{ url_for('static', filename='bootstrap-4.1.3-dist/css/bootstrap.min.css')}}"> </head> <body> <header> {% block header %} {% set user = session["user"] %} Login - {% if user %} {{ user }} {% else %} Nejsi přihlášen {% endif %}<br> <a href = "{{ url_for('odhlasit') }}">Odhlásit</a> {% endblock %} </header> <div id="content"> {% block content %} {% endblock %} </div> <footer> {% block footer %} Prostý footer {% endblock %} </footer> </body> </html>
Tiež chceme, aby sa vypisovať prihlásený používateľ v galérii a preto
šablónu root/templates/galerie.html
tiež upravíme:
{% extends "base.html" %} {% block header %} Galerie<br> {{ super() }} {% 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 %}
Ukážkovú stránku s kalkulačkou už nepotrebujeme a preto ju odstránime,
namiesto toho budeme presmerovávať používateľov na galériu. Zmažeme
template root/templates/template.html
, keďže ho už
nepotrebujeme. Ďalej zmažeme triedu MujFormular
a upravíme
funkciu kalkulacka()
v main.py
:
@app.route("/") def kalkulacka(): return redirect(url_for("galerie"))
Výsledný web vyzerá takto:
Modulárny Aplikácia
Microframework Flask obsahuje takzvané Blueprint, ktoré
nám dovoľujú rozdeliť aplikáciu na jednotlivé moduly ako napríklad
login
a galerie
. Určite uznáte, že náš súbor
main.py
je už pomerne neprehľadný a to máme stále veľmi
triviálne aplikáciu. Aby sme si aplikáciu mohli rozdeliť na moduly, musíme
si najskôr upraviť adresárovú štruktúru:
root
static
- ...
templates
base.html
login
login.py
templates
login.html
galerie
galerie.py
templates
galerie.html
__init__.py
main.py
Blueprint
s
názvom název modulu + _page
. Prvým parametrom je názov modulu,
ten sa používa napríklad pre routovanie. Druhým parametrom je názov
importovaného modulu, ten Flask používa na získanie cesty k modulu. My
nastavíme tiež template_folder
, čo je zložka s šablónami.
Hlavné main.py
teraz slúži len pre spustenie aplikácie a
jeho obsah je nasledujúci:
from root import app if __name__ == "__main__": app.run(debug=True)
root/__init__.py
obsahuje základ / inicializácii aplikácie a
presmerovanie na galériu:
from flask import Flask, redirect, url_for from root.galerie.galerie import galerie_page from root.login.login import login_page app = Flask(__name__) # Musíme nastavit SECRET_KEY, pokud chceme používat CSRF app.config["SECRET_KEY"] = "super tajny klic" app.register_blueprint(galerie_page) app.register_blueprint(login_page) # Nastavíme složku, kam se budou obrázky ukládat UPLOAD_FOLDER = app.static_folder + "/uploads/" app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER @app.route("/") def kalkulacka(): return redirect(url_for("galerie_page.galerie"))
Súbor root/login/login.py
obsahuje logiku stránky pre
prihlásenie:
from flask import render_template, url_for, session, redirect, Blueprint from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField from wtforms.validators import InputRequired login_page = Blueprint("login_page", __name__, template_folder = "templates") class LoginForm(FlaskForm): user = StringField("Uživatel", validators = [InputRequired()], render_kw = dict(class_ = "form-control")) #Přihlašovací jméno password = PasswordField("Heslo", validators = [InputRequired()], render_kw = dict(class_ = "form-control")) #Heslo submit = SubmitField("Odeslat", render_kw = dict(class_ = "btn btn-outline-primary btn-block")) @login_page.route("/login/", methods = ["GET", "POST"]) def login(): form = LoginForm() if form.validate_on_submit(): user = form.user.data password = form.password.data if password == "letmein": session["user"] = user return render_template("login.html", form = form) @login_page.route("/logout/", methods = ["GET", "POST"]) def odhlasit(): session.pop("user", None) return redirect(url_for("login_page.login"))
A súbor root/galerie/galerie.py
obsahuje logiku stránky s
galériou:
from flask import render_template, Blueprint from flask_wtf import FlaskForm from wtforms import FileField, SubmitField from flask_wtf.file import FileRequired from werkzeug.utils import secure_filename import os import root galerie_page = Blueprint("galerie_page", __name__, template_folder = "templates") class FileFormular(FlaskForm): soubor = FileField("Vlož obrázek", validators = [FileRequired()]) submit = SubmitField("Odeslat", render_kw = dict(class_ = "btn btn-outline-primary btn-block")) @galerie_page.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(root.app.config['UPLOAD_FOLDER'], nazev)) obrazky = os.listdir(root.app.static_folder + "/uploads") return render_template("galerie.html", form = form, obrazky = obrazky)
Jednotlivé šablóny zostávajú rovnaké Ak ste sa pri rozdelení aplikácie do modulov stratili, stiahnite si priloženú ukážku.
V budúcej lekcii, Zobrazenie správ a vlastné 404 stránka vo Flask , sa naučíme používať mechanizmus užívateľských správ a nastavíme si vlastný chybovú stránku.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 144x (649.88 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python