Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.
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áš movie_detail() si odstránime z views.py, odkaz na tento view odstránime aj z urls.py a nakoniec odstránime celý súbor movie_detail.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 Movie

class MovieIndex(generic.ListView):

    template_name = "moviebook/movie_index.html"  # path to the template from the templates folder (can be shared between applications)
    context_object_name = "movies"  # we will call the list of objects in the template under this name

# this method gives us a list of movies sorted by the largest id (9,8,7...)
    def get_queryset(self):
        return Movie.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("movie_index/", views.MovieIndex.as_view(), name="movie_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 movie_index.html s nasledujúcim obsahom:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    {% for movie in movies %}
        Title: {{ movie.title }} <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/movie_index/ sa nám po spustení servera zobrazí zoznam všetkých našich existujúcich filmov:

localhost:8000/mo­viebook/movie_in­dex
localhost:8000/mo­viebook/movie_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 CurrentMovie(generic.DetailView):

    model = Movie
    template_name = "moviebook/movie_detail.html"

Trieda CurrentMovie 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 movie_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="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <h1> {{ movie.title }} </h1> <small> {{ movie.director}} </small>
    <h3> {{ movie.genre.genre_name }} </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("movie_index/", views.MovieIndex.as_view(), name="movie_index"),
    path("<int:pk>/movie_detail/", views.CurrentMovie.as_view(), name="movie_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 movie_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="movie_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 movie_index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    {% for movie in movies %}
       <a href="{% url 'movie_detail' movie.id %}"> Title: {{ movie.title }} <br> </a>
    {% endfor %}
</body>
</html>

Po znovunačítaní adresy http://localhost:8000/moviebook/movie_index/ budú už filmy v zozname ako odkazy:

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

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

localhost:8000/mo­viebook/2/movi­e_detail
localhost:8000/mo­viebook/2/movi­e_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 Movie

class MovieForm(forms.ModelForm):

    class Meta:
        model = Movie
        fields = ["title", "director", "genre"]

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 Movie
from .forms import MovieForm  # New 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 CreateMovie(generic.edit.CreateView):

    form_class = MovieForm
    template_name = "moviebook/create_movie.html"

# Method for GET request, only displays the form
    def get(self, request):
        form = self.form_class(None)
        return render(request, self.template_name, {"form": form})

# Method for POST request, checks the form; if it is valid, creates a new movie; if not, displays the form with an error message
    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("movie_index/", views.MovieIndex.as_view(), name="movie_index"),
    path("<int:pk>/movie_detail/", views.CurrentMovie.as_view(), name="movie_detail"),
    path("create_movie/", views.CreateMovie.as_view(), name="new_movie"),
]

Šablóna pre CreateView

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <form method="POST">
        {% csrf_token %} <!-- Django requires authentication against csrf attack  -->
        {{ form }}
        <input type="submit">
    </form>
</body>
</html>

Výsledný formulár vyzerá takto:

http://127.0.0­.1:8000/movie­book/create_mo­vie/
http://127.0.0­.1:8000/movie­book/create_mo­vie/

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/movie_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é 3x (53.78 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