7. diel - Databázy filmov v Django - Generic Views a Formuláre
V minulej lekcii, Databázy filmov v Django - Databáza , sme si vytvorili modely, naučili sa migrovať databázu a pracovať s Django administráciou. V dnešnej lekcii sa budeme venovať generic views, pomocou ktorých s databázou naučíme pracovať našej aplikácii.
Generic views
Generic views sú predpripravené views pre jednoduché akcie, ktoré sa vo webových aplikáciách často používajú. Práve tie využijeme pre pridávanie a editáciu záznamov v našej databáze, aby sme nemuseli písať všetko znova.
Než sa na ne vrhneme, vytvorte si pomocou databázové administrácie v
databáze niekoľko ďalších filmov a pokojne aj žánrov, aby sme mali views
na čom skúšať. Náš index
view si odstránime z
views.py
, odkaz na tento view odstránime z urls.py
a
nakoniec tiež odstránime súbor
/mysite/moviebook/templates/moviebook/index.html
.
ListView
Ako prvý generic view si vyskúšame ListView, ktoré vypíše zoznam
položiek. V našom prípade si ním samozrejme necháme vypísať všetky filmy
v databáze. Súbor /mysite/moviebook/views.py
teraz upravíme do
nasledujúcej podoby:
from django.shortcuts import render from django.views import generic from .models import Film class FilmIndex(generic.ListView): template_name = "moviebook/film_index.html" # cesta k templatu ze složky templates (je možné sdílet mezi aplikacemi) context_object_name = "filmy" # pod tímto jménem budeme volat list objektů v templatu # tato funkce nám získává list filmů seřazených od největšího id (9,8,7...) def get_queryset(self): return Film.objects.all().order_by("-id")
Ako prvé je potrebné naimportovať generic views a samotné modely. View
teraz už nie je tvorené obyčajnou metódou, ale triedou dedičov z
generic.ListView
, prípadne z iného generického pohľadu. Keď sa
nad tým zamyslíte, je to logické, pretože práve dedičnosťou sa nám do
view dostane predpripravená funkčnosť. Generic view nastavíme šablónu a
ako sa má premenná s jednotlivými prvkami zoznamu v šablóne vymenovať.
Následne definujeme metódu pre získanie všetkých filmov, ktoré si
zoradíme od posledne pridaných po tie najstaršie.
Na tento view si vytvoríme odkaz v
/mysite/moviebook/urls.py
from django.urls import path from . import views urlpatterns = [ path("film_index/", views.FilmIndex.as_view(), name="filmovy_index"), ]
Template pre náš prvý generic view ListView
bude v súbore
/mysite/moviebook/templates/moviebook/film_index.html
s
nasledujúcim obsahom:
<!DOCTYPE html> <html lang="cs"> <head> <meta charset="UTF-8"> </head> <body> {% for film in filmy %} Název: {{film.nazev}} <br> {% endfor %} </body> </html>
Súbor nezabudnite ako vždy uložiť v kódovaní UTF-8.
Na adrese http://localhost:8000/moviebook/film_index/
sa nám
zobrazí zoznam všetkých našich existujúcich filmov:
DetailView
Teraz by bolo dobré vytvoriť si aj view pre detail vybraného filmu. K tomu
nám pomôže DetailView
, ktoré nám o filme zobrazia všetky
podrobnosti. Na koniec /mysite/moviebook/views.py
pridáme:
class CurrentFilmView(generic.DetailView): model = Film template_name = "moviebook/film_detail.html"
View je opäť trieda, odděděná z generického predka. V prípade detaile nastavujeme len model a názov šablóny.
Šablóna
Šablónu pre view vytvoríme v
/mysite/moviebook/templates/moviebook/film_detail.html
, ktorý sme
v detail view vyššie nastavili. Všimnite si pomenovanie súborov, kedy je
názov zložený z názvu entity, podčiarknutia a názvu generic view. Obsah
šablóny je nasledujúci:
<!DOCTYPE html> <html lang="cs"> <head> <meta charset="UTF-8"> </head> <body> <h1> {{ film.nazev }} </h1><small> {{ film.rezie }} </small> <h3> {{film.zanr.nazev_zanru}} </h3> </body> </html>
Uložte v UTF-8.
Každý DetailView
potrebuje poznať ID / PK (primárny kľúč)
konkrétneho filmu, pre ktorý nám bude zobrazovať všetky informácie, aby si
ho mohol z databázy načítať. Odkaz na film preto bude obsahovať aj PK
konkrétneho filmu. Upravíme súbor /mysite/moviebook/urls.py
:
from django.urls import path from . import views urlpatterns = [ path("film_index/", views.FilmIndex.as_view(), name="filmovy_index"), path("<int:pk>/film_detail/", views.CurrentFilmView.as_view(), name="filmovy_detail"), ]
Tým sme Dajngo vysvetlili, že keď niekto zadá URL adresu na detail filmu, je to číslo pred ňou primárny kľúč (ID) tohto filmu.
Teraz odkaz na film pridáme do výpisu filmov, teda do šablóny
/mysite/moviebook/templates/moviebook/film_index.html
. Obyčajný
užívateľ sa totiž zatiaľ stále nemá ako dostať na stránku s
informáciami o filme. Do odkazu nezadáme absolútnu adresu, ale použijeme
názov URL, ktorý sme v routách uviedli (v tomto prípade
name="filmovy_detail"
), ako parameter odovzdáme ID / PK. URL je
takto jednoduchšie a keby sa adresa pohľadu niekedy zmenila, táto zmena sa
prejaví bez nutnosti šablónu upraviť. Pridajme teda odkaz do
film_index.html
:
<!DOCTYPE html> <html lang="cs"> <head> <meta charset="UTF-8"> </head> <body> {% for film in filmy %} <a href={% url "filmovy_detail" film.id %}> Název: {{film.nazev}} <br> </a> {% endfor %} </body> </html>
Po opätovnom otvorení adresy
http://localhost:8000/moviebook/film_index/
budú už filmy v
zozname ako odkazy:
Po kliknutí na film budeme presmerovaný na detail daného filmu:
Ak však užívateľ bude natoľko trúfalý a zadá do URL ID neexistujúceho objektu, view nám vyhodí error 404.
Formulár
Filmy vieme vypisovať a zobrazovať ich detail. Ale čo film pridať alebo
upraviť? Na tento účel si vytvoríme formulár, čo urobíme pomocou triedy
ModelForm
. Formulár by sme samozrejme mohli vytvoriť oldschool
cestou len ako čisté HTML, ako sme to robili v kalkulačke, ale Django tu
máme práve preto, aby sme sa naučili ako si s ním uľahčiť prácu.
Vytvoríme si nový modul /mysite/moviebook/forms.py
, v ktorom sa
bude nachádzať náš formulár.
from django import forms from .models import Film class FilmForm(forms.ModelForm): class Meta: model = Film fields=["nazev", "rezie", "zanr"]
Asi vás neprekvapí, že ako ďalší krok si vytvoríme view, ktoré bude
stránku s formulárom obsluhovať. Prejdeme do
/mysite/moviebook/views.py
, kde pridáme nový import práve na
náš formulár:
from django.shortcuts import render, redirect, render_to_response from django.views import generic from .models import Film from .forms import FilmForm #Nový import # ...
CreateView
Okrem importu na koniec súboru pridáme obsluhu formulára, ktorú si
vzápätí vysvetlíme. Použijeme pre ňu generic view CreateView
.
Vidíme ako môžeme z Django prevziať veľa funkcionality, ktorú by sme inak
museli implementovať sami.
# ... class CreateFilm(generic.edit.CreateView): form_class = FilmForm template_name = "moviebook/create_film.html" # Metoda pro GET request, zobrazí pouze formulář def get(self, request): form = self.form_class(None) return render(request, self.template_name, {"form":form}) # Metoda pro POST request, zkontroluje formulář; pokud je validní, vytvoří nový film; pokud ne, zobrazí formulář s chybovou hláškou def post(self, request): form = self.form_class(request.POST) if form.is_valid(): form.save(commit=True) return render(request, self.template_name, {"form":form})
View nastavujeme formulár a šablónu. Ďalej obsahuje 2 akcie,
get()
formulár iba zobrazuje a post()
ho spracováva
v prípade, že už bol odoslaný. Všimnite si, že v oboch akciách formulár
odovzdávame pomocou listu do šablóny, aby sme ho tam mohli vykresliť.
Určite by sme sa nemali v metóde post()
zabudnúť opýtať, či
bol formulár validný vyplnený. Keďže formulár vie aký model spracúva,
pre uloženie filmu na ňom stačí zavolať len metódu save()
a
je hotovo.
Pre nových view a teda novú adresu si ako vždy pridáme route v
/mysite/moviebook/urls.py
.
from django.urls import path from . import views urlpatterns = [ path("film_index/", views.FilmIndex.as_view(), name="filmovy_index"), path("<int:pk>/film_detail/", views.CurrentFilmView.as_view(), name="filmovy_detail"), path("create_film/", views.CreateFilm.as_view(), name="novy_film"), ]
Šablóna
Vytvoríme si template
/mysite/moviebook/templates/moviebook/create_film.html
pre náš
formulár, ktorý bude veľmi primitívne.
<!DOCTYPE html> <html lang="cs"> <head> <meta charset="UTF-8"> </head> <body> <form method="POST"> {% csrf_token %} <!-- Django požaduje ověření proti útoku csrf --> {{ form }} <input type="submit"> </form> </body> </html>
Uložíme v UTF-8. Výsledný formulár vyzerá zatiaľ takto:
Náš formulár nie je príliš pekný, ale to v nasledujúcej lekcii
zmeníme za pomoci django-crispy-forms. Po odoslaní validného formulára sa
vytvorí nový film. Po prechode na
http://localhost:8000/moviebook/film_index
si môžete vyskúšať,
že sa medzi filmami naozaj zobrazí. Naša aplikácia začína byť reálne
použiteľná
To je pre dnešné lekciu všetko. Nabudúce by som rád v lekcii Databázy filmov v Django - Crispy forms a Bootstrap prebral "base template", už zmieňované django-crispy-form a vytvoríme si DB model používateľa.
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é 135x (133.18 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python