Lekce 4 - Kalkulačka v Django frameworku
V minulé lekci, Představení MVC a MVT architektury v Django, jsme si popsali MVT (MVC) architekturu.
V následujícím tutoriálu webových aplikací s frameworkem Django v Pythonu využijeme naše znalosti MVC architektury pro tvorbu základní jednoduché kalkulačky, která bude sčítat, odečítat, násobit a dělit. V dnešní lekci si MVC architekturu poprvé vyzkoušíme v praxi.
Kalkulačka v Django
Naše kalkulačka bude opravdu poměrně jednoduchá. Naučíme ji provádět pouze základní matematické operace:
- sčítání,
- odčítání,
- násobení,
- dělení.
Aplikace bude mít dvě vstupní políčka <input>
pro
čísla, jedno tlačítko <input type="submit">
pro
odeslání formuláře a <select>
na výběr operace s
možnostmi +
, -
, *
a /
. V
prohlížeči bude vypadat takto:
Pusťme se do toho.
Vytvoření projektu
Webová aplikace v podání Django frameworku bude projekt s jednou aplikací
s názvem calculator
. Z předchozích lekcí již máme vytvořený
projekt mysite
, zadali jsme totiž příkaz:
django-admin startproject mysite
Již víme, že projekt může obsahovat více aplikací, a tak můžeme kalkulačku přidat klidně do tohoto stejného projektu. Pokud tento projekt vytvořený nemáme, spustíme kód výše. Pokud máme, vypíše nám chybovou hlášku, že projekt již existuje.
Vytvoření aplikace
Přesuneme se do složky mysite/
a otevřeme příkazový
řádek. Jak složku s Django projekty otevřít a jak v ní otevřít
příkazový řádek jsme si podrobně ukazovali v lekci Seznámení s
Django frameworkem pro Python. V příkazovém řádku spustíme příkaz
pro vytvoření nové aplikace calculator
v tomto projektu:
py manage.py startapp calculator
Jelikož se po provedení příkazu nic nevypíše, můžeme si jeho
úspěšnost ověřit tím, že se podíváme, zda se ve složce
mysite/
vytvořila nová složka calculator/
.
Instalace aplikace
Postupujeme úplně stejně jako s naší první aplikací. Aplikaci je nyní
třeba nainstalovat a proto v souboru/modulu (modul rovná se soubor, jelikož v
Pythonu se každému souboru říká modul)
\mysite\mysite\settings.py
aplikaci do seznamu aplikací
přidáme:
INSTALLED_APPS = [ 'calculator', 'ahoj_svete', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
Routování
Přejděme k routování, tedy navazování URL adres na jednotlivá views.
Nyní je třeba importovat všechny URL adresy z aplikace do hlavního
schématu URL adres, které se vždy nachází v
\nazev_projektu\nazev_projektu\urls.py
, což je u nás
\mysite\mysite\urls.py
:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include("ahoj_svete.urls")), path("calculator_aplikace/", include("calculator.urls")), ]
Všimněme si, že nyní do calculator.urls
nenapojujeme kořenovou adresu projektu localhost:8000
jako u
Ahoj světe
, ale kalkulačka poběží na adrese
localhost:8000/calculator_aplikace
. Jednotlivé aplikace našeho
projektu budeme nyní dávat do složek, aby se všechny nehádaly o jednu URL
adresu.
Routy aplikace
Routy projektu máme napojené na routy aplikace. Nyní musíme vytvořit
routy aplikace odkazující na view, které bude URL adresu kalkulačky
obsluhovat. Toto view vytvoříme později. Vytvořme tedy soubor
mysite\calculator\urls.py
a vložme do něj následující
kód:
from django.urls import path from . import views urlpatterns = [ path("", views.kalkulacka, name="kalkulacka"), ]
Šablona
Před tím, než začneme psát logiku aplikace, si vytvoříme šablonu.
Bude se nacházet v
mysite\calculator\templates\calculator\kalkulacka.html
. Vytvořme
si tedy složku templates/
, v ní podsložku
calculator/
a v ní soubor kalkulacka.html
. Vložme do
něj následující obsah:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Webová kalkulačka v Pythonu</title> </head> <body> <form method="POST"> {% csrf_token %} <input type="text" name="a"> <select name="operator"> <option value="+">+</option> <option value="-">-</option> <option value="*">*</option> <option value="/">/</option> </select> <input type="text"><br> <input type="submit"> </form> </body> </html>
Dáme si pozor, aby byl soubor vytvořený v UTF-8 kódování! To platí pro všechny soubory, které budeme vytvářet.
CSRF útok
Pravděpodobně nás v kódu formuláře zaujala direktiva
{% csrf_token %}
. V každém formuláři Django vyžaduje
tzv. CSRF "žeton", který slouží proti útoku podvržení
formuláře. CSRF token opatří formulář "žetonem", pomocí
kterého se ověřuje, že byl odeslán přes naší stránku a ne přes
stránku cizí.
Představme si situaci, kdy jsme vytvořili nějaký populární
blog a někdo by vytvořil úplně jinou stránku, kam by dal formulář
vybízející ke vkládání vulgárních příspěvků. Tento formulář by
ovšem nenechal odesílat data na jeho stránku, ale na view našeho blogu. Nic
netušící uživatelé by rázem psali příspěvky na náš blog, i když by
se na této stránce vůbec nenacházeli a nevěděli, že tam něco posílají.
Tento zmíněný útok by byl ještě poměrně neškodný, ale co potom takový
falešný formulář na odesílání peněz... Jaj
Vytvoření modelu
Nyní vytvoříme logiku aplikace, tedy funkce, které nám budou vracet
výsledky. Takovou logiku nikdy nepíšeme přímo do view, ale do modelu.
Představme si, jak by jinak vypadaly větší aplikace, náš soubor s views by
byl dlouhý a nepřehledný. Toto rozdělení jsme si již vysvětlovali při
popisu MVC architektury. Do \mysite\calculator\models.py
napíšeme
následující kód:
def secti(a, b): return float(a) + float(b) def odecti(a, b): return float(a) - float(b) def vydel(a, b): return float(a) / float(b) def vynasob(a, b): return float(a) * float(b)
Padly zde termíny "model" a "modul", ty nezaměňujme. Model je součást MVC architektury, modul je Python soubor. Každý náš model bude modulem, ale ne každý náš modul bude modelem.
Vytvoření view
Docílili jsme toho, že se po zadání URL adresy
localhost:8000/calculator_aplikace
spustí view
kalkulacka()
. To je metoda v souboru views.py
, kde
uživatelský požadavek obsloužíme. Samozřejmě k tomu použijeme
model a template
Jak již víme, každá funkce view má povinný parametr
request
, kam se předá uživatelský požadavek. Náš view bude
jistě využívat i funkci render()
, jelikož bude vracet HTML
šablonu s formulářem. Dále přijme POST
požadavek, tedy data
odeslaná tímto formulářem, provede vyžadovanou operaci a vrátí výsledek.
Ale to až za chvilku.
Nejdříve si v modulu \mysite\calculator\views.py
vytvoříme
funkci kalkulacka()
, na kterou již odkazujeme ze souboru
mysite\calculator\urls.py
:
from django.shortcuts import render def kalkulacka(request): error_msg = None vysledek = None
Validace
Dále potřebujeme zjistit, zda byly vyplněny obě číslice, zda jsou to vůbec číslice, a zda byl odeslán operátor. V našich aplikacích bychom měli předpokládat, že se uživatel může splést nebo že do nich úmyslně pošle nějaký nesmysl. Formulář tedy nejprve zvalidujeme. Pokud nastane výjimka, vrátíme naši HTML šablonu s chybovou hláškou:
from django.shortcuts import render def kalkulacka(request): error_msg = None vysledek = None if request.method == "POST": try: float(request.POST["a"]) float(request.POST["b"]) except: error_msg = "A nebo B není číslo!" return render(request, "calculator/kalkulacka.html", dict(error_msg=error_msg, vysledek=vysledek))
Vše je ošetřeno.
Zbýva nám naimportovat náš model, předat mu data a výsledek předat šabloně. Přesně toto je účelem view:
from django.shortcuts import render from . import models def kalkulacka(request): error_msg = None vysledek = None if request.method == "POST": try: float(request.POST["a"]) float(request.POST["b"]) except: error_msg = "A nebo B není číslo!" return render(request, "calculator/kalkulacka.html", dict(error_msg=error_msg, vysledek=vysledek)) if request.POST["operator"] == "/" and float(request.POST["b"]) == 0: error_msg = "Chyba dělení nulou" return render(request, "calculator/kalkulacka.html", dict(error_msg=error_msg, vysledek=vysledek)) if request.POST["operator"] == "+": vysledek = models.secti(request.POST["a"], request.POST["b"]) elif request.POST["operator"] == "-": vysledek = models.odecti(request.POST["a"], request.POST["b"]) elif request.POST["operator"] == "/": vysledek = models.vydel(request.POST["a"], request.POST["b"]) elif request.POST["operator"] == "*": vysledek = models.vynasob(request.POST["a"], request.POST["b"]) else: error_msg = "Něco se pokazilo :(" return render(request, "calculator/kalkulacka.html", dict(error_msg=error_msg, vysledek=vysledek)) return render(request, "calculator/kalkulacka.html", dict(error_msg=error_msg, vysledek=vysledek))
Úprava šablony
Aby v šabloně zůstávala vyplněná data a zobrazovala chybové hlášky,
je třeba v ní vypsat obsah error_msg
, kterou jsme si ve view
připravili. Také aplikujeme zlepšovák, který nám po odeslání bude
zobrazovat v <input>
políčkách čísla, která jsme
zadali, a ponechá vybraný operátor:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Webová kalkulačka v Pythonu</title> </head> <body> <form method="POST"> {% csrf_token %} <span style="color: red;">{{error_msg}}</span> <br> <input type="text" name="a" value={{request.POST.a}}> <select name="operator"> <option value="+" {% if request.POST.operator == "+" %} selected {% endif %}>+</option> <option value="-" {% if request.POST.operator == "-" %} selected {% endif %}>-</option> <option value="*" {% if request.POST.operator == "*" %} selected {% endif %}>*</option> <option value="/" {% if request.POST.operator == "/" %} selected {% endif %}>/</option> </select> <input type="text" name="b" value={{request.POST.b}}><br> <input type="submit"><br> {{vysledek}} </form> </body> </html>
Spuštění
Kalkulačku nalezneme na adrese
http://localhost:8000/calculator_aplikace/
. Samozřejmě musíme
prvně spustit server příkazem py manage.py runserver
a to ze
složky se souborem manage.py
, dělali jsme v minulých
lekcích.
Výsledek:
Zdrojové kódy jsou přiloženy na konci lekce.
V následujícím kvízu, Kvíz - Základy frameworku Django, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
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 412x (8.93 kB)
Aplikace je včetně zdrojových kódů v jazyce Python