4. diel - Kalkulačka v Django frameworku
V minulej lekcii, Predstavenie MVC a MVT architektúry v Django, sme si popísali MVT (MVC) architektúru.
V nasledujúcom tutoriáli webových aplikácií s frameworkom Django v Pythone využijeme naše znalosti MVC architektúry pre tvorbu základnej jednoduchej kalkulačky, ktorá bude sčítať, odčítať, násobiť a deliť. V dnešnej lekcii si MVC architektúru po prvýkrát vyskúšame v praxi.
Kalkulačka v Django
Naša kalkulačka bude skutočne pomerne jednoduchá. Naučíme ju vykonávať iba základné matematické operácie:
- sčítanie,
- odčítanie,
- násobenie,
- delenie.
Aplikácia bude mať dve vstupné políčka <input>
pre
čísla, jedno tlačidlo <input type="submit">
pre odoslanie
formulára a <select>
na výber operácie s možnosťami
+
, -
, *
a /
. V prehliadači
bude vyzerať takto:
Pusťme sa do toho.
Vytvorenie projektu
Webová aplikácia v podaní Django frameworku bude projekt s jednou
aplikáciou s názvom calculator
. Z predchádzajúcich lekcií už
máme vytvorený projekt mysite
, zadali sme totiž príkaz:
django-admin startproject mysite
Už vieme, že projekt môže obsahovať viacero aplikácií, a tak môžeme kalkulačku pridať pokojne do tohto rovnakého projektu. Pokiaľ tento projekt vytvorený nemáme, spustíme kód vyššie. Ak máme, vypíše nám chybovú hlášku, že projekt už existuje.
Vytvorenie aplikácie
Presunieme sa do zložky mysite/
a otvoríme príkazový riadok.
Ako zložku s Django projektmi otvoriť a ako v nej otvoriť príkazový riadok
sme si podrobne ukazovali v lekcii Zoznámenie s
Django frameworkom pre Python. V príkazovom riadku spustíme príkaz na
vytvorenie novej aplikácie calculator
v tomto projekte:
py manage.py startapp calculator
Keďže sa po vykonaní príkazu nič nevypíše, môžeme si jeho
úspešnosť overiť tým, že sa pozrieme, či sa v zložke
mysite/
vytvorila nová zložka calculator/
.
Inštalácia aplikácie
Postupujeme úplne rovnako ako s našou prvou aplikáciou. Aplikáciu je
teraz potrebné nainštalovať a preto v súbore/module (modul rovná sa
súboru, pretože v Pythone sa každému súboru hovorí modul)
\mysite\mysite\settings.py
aplikáciu do zoznamu aplikácií
pridáme:
INSTALLED_APPS = [ 'calculator', 'hello_world', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
Routovanie
Prejdime k routovaniu, teda nadväzovaniu URL adries na jednotlivé views.
Teraz je potrebné importovať všetky URL adresy z aplikácie do hlavnej
schémy URL adries, ktoré sa vždy nachádza v
\project_name\project_name\urls.py
, čo 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("hello_world.urls")), path("calculator_application/", include("calculator.urls")), ]
Všimnime si, že teraz do calculator.urls
nenapájame koreňovú adresu projektu localhost:8000
ako u
Hello world
, ale kalkulačka pobeží na adrese
localhost:8000/calculator_application
. Jednotlivé aplikácie
nášho projektu budeme teraz dávať do zložiek, aby sa všetky nehádali o
jednu URL adresu.
Routy aplikácie
Routy projektu máme napojené na routy aplikácie. Teraz musíme vytvoriť
routy aplikácie odkazujúce na view, ktoré bude URL adresu kalkulačky
obsluhovať. Toto view vytvoríme neskôr. Vytvorme teda súbor
mysite\calculator\urls.py
a vložme do neho nasledujúci kód:
from django.urls import path from . import views urlpatterns = [ path("", views.calculator, name="calculator"), ]
Šablóna
Pred tým, než začneme písať logiku aplikácie, si vytvoríme šablónu.
Bude sa nachádzať v
mysite\calculator\templates\calculator\calculator.html
. Vytvorme si
teda zložku templates/
, v nej podzložku calculator/
a v nej súbor calculator.html
. Vložme do neho nasledujúci
obsah:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Python web calculator</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" name="b"><br> <input type="submit"> </form> </body> </html>
Dáme si pozor, aby bol súbor vytvorený v UTF-8 kódovaní! To platí pre všetky súbory, ktoré budeme vytvárať.
CSRF útok
Pravdepodobne nás v kóde formulára zaujala direktíva
{% csrf_token %}
. V každom formulári Django vyžaduje
tzv. CSRF "žetón", ktorý slúži proti útoku podvrhnutia
formulára. CSRF token opatrí formulár "žetónom", pomocou ktorého
sa overuje, že bol odoslaný cez našu stránku a nie cez stránku cudziu.
Predstavme si situáciu, kedy sme vytvorili nejaký populárny
blog a niekto by vytvoril úplne inú stránku, kam by dal formulár
nabádajúci na vkladanie vulgárnych príspevkov. Tento formulár by však
nenechal odosielať dáta na jeho stránku, ale na view nášho blogu. Nič
netušiaci používatelia by razom písali príspevky na náš blog, aj keď by
sa na tejto stránke vôbec nenachádzali a nevedeli, že tam niečo posielajú.
Tento spomínaný útok by bol ešte pomerne neškodný, ale čo potom taký
falošný formulár na odosielanie peňazí... Jaj
Vytvorenie modelu
Teraz vytvoríme logiku aplikácie, teda funkcie, ktoré nám budú vracať
výsledky. Takú logiku nikdy nepíšeme priamo do view, ale do modelu.
Predstavme si, ako by inak vyzerali väčšie aplikácie, náš súbor s views
by bol dlhý a neprehľadný. Toto rozdelenie sme si už vysvetľovali pri opise
MVC architektúry. Do \mysite\calculator\models.py
napíšeme
nasledujúci kód:
def add(a, b): return float(a) + float(b) def subtract(a, b): return float(a) - float(b) def divide(a, b): return float(a) / float(b) def multiply(a, b): return float(a) * float(b)
Padli tu termíny "model" a "modul", tie nezamieňajte. Model je súčasť MVC architektúry, modul je Python súbor. Každý náš model bude modulom, ale nie každý náš modul bude modelom.
Vytvorenie view
Docielili sme to, že sa po zadaní URL adresy
localhost:8000/calculator_application
spustí view
calculator()
. To je metóda v súbore views.py
, kde
používateľskú požiadavku obslúžime. Samozrejme na to použijeme
model a template
Ako už vieme, každá funkcia view má povinný parameter
request
, kam sa odovzdá používateľská požiadavka. Náš view
bude určite využívať aj funkciu render()
, pretože bude vracať
HTML šablónu s formulárom. Ďalej prijme POST
požiadavku, teda
dáta odoslané týmto formulárom, vykoná vyžadovanú operáciu a vráti
výsledok. Ale to až za chvíľku.
Najskôr si v module \mysite\calculator\views.py
vytvoríme
funkciu calculator()
, na ktorú už odkazujeme zo súboru
mysite\calculator\urls.py
:
from django.shortcuts import render def calculator(request): error_msg = None result = None
Validácia
Ďalej potrebujeme zistiť, či boli vyplnené obe číslice, či sú to vôbec číslice a či bol odoslaný operátor. V našich aplikáciách by sme mali predpokladať, že sa používateľ môže pomýliť alebo že do nich úmyselne pošle nejaký nezmysel. Formulár teda najskôr zvalidujeme. Pokiaľ nastane výnimka, vrátime našu HTML šablónu s chybovou hláškou:
from django.shortcuts import render def calculator(request): error_msg = None result = None if request.method == "POST": try: float(request.POST["a"]) float(request.POST["b"]) except: error_msg = "A or B is not a number!" return render(request, "calculator/calculator.html", dict(error_msg=error_msg, result=result))
Všetko je ošetrené.
Zostáva nám naimportovať náš model, odovzdať mu dáta a výsledok odovzdať šablóne. Presne toto je účelom view:
from django.shortcuts import render from . import models def calculator(request): error_msg = None result = None if request.method == "POST": try: float(request.POST["a"]) float(request.POST["b"]) except: error_msg = "A or B is not a number!" return render(request, "calculator/calculator.html", dict(error_msg=error_msg, result=result)) if request.POST["operator"] == "/" and float(request.POST["b"]) == 0: error_msg = "Division by zero error" return render(request, "calculator/calculator.html", dict(error_msg=error_msg, result=result)) if request.POST["operator"] == "+": result = models.add(request.POST["a"], request.POST["b"]) elif request.POST["operator"] == "-": result = models.subtract(request.POST["a"], request.POST["b"]) elif request.POST["operator"] == "/": result = models.divide(request.POST["a"], request.POST["b"]) elif request.POST["operator"] == "*": result = models.multiply(request.POST["a"], request.POST["b"]) else: error_msg = "Something went wrong :(" return render(request, "calculator/calculator.html", dict(error_msg=error_msg, result=result)) return render(request, "calculator/calculator.html", dict(error_msg=error_msg, result=result))
Úprava šablóny
Aby v šablóne zostávali vyplnené dáta a zobrazovala chybové hlášky,
treba v nej vypísať obsah error_msg
, ktorú sme si vo view
pripravili. Tiež aplikujeme zlepšovák, ktorý nám po odoslaní bude
zobrazovať v <input>
políčkach čísla, ktoré sme zadali,
a ponechá vybraný operátor:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Python web calculator</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> {{result}} </form> </body> </html>
Spustenie
Kalkulačku nájdeme na adrese
http://localhost:8000/calculator_application/
. Samozrejme musíme
prvýkrát spustiť server príkazom py manage.py runserver
a to zo
zložky so súborom manage.py
, robili sme v minulých
lekciách.
Výsledok:
Zdrojové kódy sú priložené na konci lekcie.
V nasledujúcom kvíze, Kvíz - Základy frameworku Django, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.
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é 8x (19.48 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python