IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

7. diel - Databáza filmov v Django - Generic Views a Formuláre

V minulej lekcii, Databáza filmov v Django - Databáza , sme si vytvorili modely, naučili sa migrovať databázu a pracovať s Django administráciou.

V dnešnom tutoriáli webových aplikácií s frameworkom Django v Pythone sa budeme venovať generic views, pomocou ktorých naučíme projekt Filmová databáza pracovať s databázou.

Úprava súborov Filmovej databázy

Než sa vrhneme do práce, vytvorme si pomocou databázovej administrácie v databáze niekoľko ďalších filmov a pokojne aj žánrov, aby sme mali pohľady na čom skúšať. Náš detail_filmu() si odstránime z views.py, odkaz na tento view odstránime aj z urls.py a nakoniec odstránime celý súbor detail_filmu.html zo zložky mysite/moviebook/templates/moviebook/.

Generic views v Djangu

Generic views sú predpripravené pohľady pre jednoduché akcie, ktoré sa vo webových aplikáciách často používajú. Práve tie využijeme na pridávanie a editáciu záznamov v našej databáze, aby sme nemuseli písať všetko znova.

ListView

Ako prvý generic view si vyskúšame ListView, ktorý nám 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 views.py v priečinku mysite/moviebook/ 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 šabloně ze složky templates (je možné sdílet mezi aplikacemi)
    context_object_name = "filmy"  # pod tímto jménem budeme volat seznam objektů v šabloně

# tato metoda nám získává seznam filmů seřazených od největšího id (9,8,7...)
    def get_queryset(self):
        return Film.objects.all().order_by("-id")

Je nám už zrejmé, čo je obsahom pojmu view. Nebudeme teda ďalej používať mix slovenčiny (pohľad) a angličtiny a budeme sa držať konvenčného anglického označenia view.

Popíšme si kód. Najprv treba naimportovať generic views a samotné modely. View teraz už nie je tvorené obyčajnou metódou, ale triedou dediacou z generic.ListView, prípadne z iného generického pohľadu. Keď sa nad tým zamyslíme, 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 volať. Následne definujeme metódu na získanie všetkých filmov, ktoré si zoradíme od naposledy pridaných po tie najstaršie.

Na tento view si vytvoríme odkaz v súbore urls.py v priečinku mysite/moviebook/:

from django.urls import path
from . import views

urlpatterns = [
    path("film_index/", views.FilmIndex.as_view(), name="filmovy_index"),
]

Šablóna pre ListView

Šablónu pre náš prvý generic view vytvoríme v priečinku mysite/moviebook/templates/moviebook/ ako nový súbor 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>

Tento súbor ani všetky nasledujúce nezabudnime ako vždy uložiť v kódovaní UTF-8.

Na adrese http://localhost:8000/moviebook/film_index/ sa nám po spustení servera zobrazí zoznam všetkých našich existujúcich filmov:

localhost:8000/mo­viebook/film_in­dex
localhost:8000/mo­viebook/film_in­dex

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 zobrazí všetky podrobnosti. Na koniec súboru views.py v priečinku mysite/moviebook/ pridáme:

class CurrentFilm(generic.DetailView):

    model = Film
    template_name = "moviebook/film_detail.html"

Trieda CurrentFilm je opäť oddedená z generického predka. V prípade detailu nastavujeme iba model a názov šablóny.

Šablóna pre DetailView

Šablónu pre DetailView vytvoríme v priečinku mysite/moviebook/templates/moviebook/ ako nový súbor film_detail.html, ktorý sme vyššie nastavili.

Všimnime si pomenovanie súborov, kedy je názov zložený z názvu entity, podčiarkovníka a názvu generic view. Tejto praxe sa budeme držať.

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>

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 preto v priečinku mysite/moviebook/ súbor 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.CurrentFilm.as_view(), name="filmovy_detail"),
]

Tým sme Django vysvetlili, že keď používateľ zadá URL adresu na detail filmu, číslo pred ňou je primárny kľúč (ID) tohto filmu.

Teraz odkaz na film pridáme do výpisu filmov, teda do šablóny film_index.html. Obyčajný použí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šia a keby sa adresa view 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 znovunačítaní adresy http://localhost:8000/moviebook/film_index/ budú už filmy v zozname ako odkazy:

localhost:8000/mo­viebook/film_in­dex
localhost:8000/mo­viebook/film_in­dex

Po kliknutí na film budeme presmerovaní na detail daného filmu:

localhost:8000/mo­viebook/2/fil­m_detail
localhost:8000/mo­viebook/2/fil­m_detail

Pokiaľ 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 teda vieme vypisovať a zobrazovať ich detail. Ale čo film pridať alebo upraviť? Za týmto účelom 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 preto v priečinku mysite/moviebook/ nový modul 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"]

Ako ďalší krok si (ako už obvykle) vytvoríme view, ktoré bude stránku s formulárom obsluhovať. Prejdeme do súboru views.py, kam pridáme nový import práve na náš formulár:

from django.shortcuts import render
from django.views import generic

from .models import Film
from .forms import FilmForm  # Nový import

# ...

CreateView

Okrem importu na koniec súboru pridáme aj obsluhu formulára, ktorú si čoskoro vysvetlíme. Použijeme pre ňu generic view CreateView. Vidíme, ako môžeme z Django prevziať množstvo 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 dve akcie, metóda get() formulár iba zobrazuje a metóda post() ho spracováva v prípade, že už bol odoslaný. Všimnime si, že v oboch akciách formulár odovzdávame pomocou slovníka 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 validne vyplnený. Keďže formulár vie, aký model spracováva, na uloženie filmu na ňom stačí zavolať len metódu save() a je hotovo.

Pre nové view a teda novú adresu si ako vždy pridáme routu v 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.CurrentFilm.as_view(), name="filmovy_detail"),
    path("create_film/", views.CreateFilm.as_view(), name="novy_film"),
]

Šablóna pre CreateView

Vytvoríme si rovnako ako v predchádzajúcich prípadoch šablónu v novom súbore create_film.html. Náš formulár zatiaľ bude veľmi primitívny:

<!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>

Výsledný formulár vyzerá takto:

http://127.0.0­.1:8000/movie­book/create_fil­m/
http://127.0.0­.1:8000/movie­book/create_fil­m/

Náš formulár zatiaľ nie je príliš pekný, ale to v budúcej lekcii zmeníme pomocou django-crispy-forms. Po odoslaní validného formulára sa vytvorí nový film. Po prechode na http://localhost:8000/moviebook/film_index si môžeme vyskúšať, že sa medzi filmami naozaj zobrazí. Naša aplikácia začína byť reálne použiteľná:)

Zdrojový kód je opäť v archíve pod lekciou.

V nasledujúcej lekcii, Databáza filmov v Django - Crispy forms a Bootstrap , si do svojej aplikácie na evidenciu filmov integrujeme django-crispy-forms a naučíme sa presmerovávať z východiskovej adresy na konkrétny pohľad.


 

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é 160x (133.18 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python

 

Predchádzajúci článok
Databáza filmov v Django - Databáza
Všetky články v sekcii
Tvorba webov v Django frameworku pre Python
Preskočiť článok
(neodporúčame)
Databáza filmov v Django - Crispy forms a Bootstrap
Článok pre vás napísal MQ .
Avatar
Užívateľské hodnotenie:
1 hlasov
Používám hlavně Python a zajímám se o Deep Learning a vše kolem.
Aktivity