Tvoříme blog v Djangu – krok za krokem
V tomto článku začneme s tvorbou naší první aplikace – jednoduchého blogu. Série článků bude zaměřená primárně na backendovou logiku, takže co se týče vzhledu, použijeme pouze Bootstrap. Nebudeme tedy používat žádný frontendový framework jako React, Vue.js nebo Angular – těm se budeme věnovat až později, až budeme řešit pokročilejší integraci s Djangem.
Co nás čeká?
Celý proces tvorby blogu rozdělíme do tří hlavních částí:
- Část 1: Základní CRUD funkce – vytvoření, úprava a mazání článků.
- Část 2: Kategorie a vyhledávání – filtrování podle kategorií a fulltextové hledání.
- Část 3: Komentáře – diskuse pod články včetně odpovědí.
Po dokončení těchto kroků přidáme správu uživatelů – registraci, přihlášení a oprávnění k článkům.
Začínáme s aplikací
Založení aplikace:
python manage.py startapp blog
Nezapomeňte přidat aplikaci do INSTALLED_APPS v settings.py.
Model příspěvku
V souboru models.py vytvoříme model, který bude reprezentovat jeden blogový příspěvek:
from django.db import models
from django_extensions.db.fields import AutoSlugField
class Post(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
slug = AutoSlugField(populate_from="title")
created = models.DateField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ['-created']
Vysvětlení polí
- CharField – krátký text (např. název článku). V tomto poly je povinný paramter max_length, který definuje maximální počet znaků.
- TextField – Vícero řádkový text bez omezení délky.
- AutoSlugField – Automatické generování URL-friendly názvu. Pro jeho použití je nutné nainstalovat knihovnu django-extensions
pip install django-extensions. - DateField – Datum vytvoření. Díky parametru auto_now_add=True se vyplní automaticky při vytvoření.
- __str__() – Vrací název článku při jeho reprezentaci (např. v adminu nebo konzoli).
- Meta.ordering – Nastaví výchozí řazení podle data vytvoření, od nejnovějšího k nejstaršímu (prefix - značí sestupné řazení).
Formulář pro článek
Pro jednodušší práci s články přes webové rozhraní si ve složce blog vytvoříme soubor forms.py:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'body']
labels = {
'title': 'Název článku',
'body': 'Obsah článku',
}
- Importujeme potřebné třídy a náš model Post.
- Vytváříme formulář jako
ModelForm, čímž Django automaticky vygeneruje vstupní pole podle modelu. - V
Metatřídě určíme, že budeme pracovat s modelemPosta že chceme zobrazit pouze poletitleabody. - Pomocí
labelsupravíme popisky polí ve formuláři.
Views – logika blogu (CRUD)
Po definování modelů a formulářů je čas přejít k "mozku" celé aplikace – views. Právě zde bude probíhat hlavní logika naší blogové aplikace: zobrazování příspěvků, jejich vytváření, úprava i mazání. Jinými slovy: CRUD operace (Create, Read, Update, Delete).
Podíváme se společně na jednotlivé funkce v souboru views.py a vysvětlíme si, co přesně dělají.
Importy
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post
from .forms import PostForm
renderslouží k vykreslení HTML šablon s daty.get_object_or_404zjednodušuje získání objektu z databáze – pokud nenajde, vrátí automaticky 404.redirectpřesměruje uživatele na jinou stránku.- Dále importujeme náš model
Posta formulářPostForm.
Jednotlivé funkce
1. Zobrazení seznamu:
def home_view(request):
posts = Post.objects.all()
return render(request, "blog/home.html", {"posts": posts})
Získáme všechny příspěvky (Post.objects.all()) a předáme je do šablony home.html, kde se zobrazí seznam článků. Tento view funguje jako hlavní stránka blogu.
2. Detail příspěvku:
def post_detail_view(request, slug):
post = get_object_or_404(Post, slug=slug)
return render(request, "blog/post_detail.html", {"post": post})
Zde načítáme konkrétní příspěvek podle jeho slugu. Pokud neexistuje, vrátí se 404. Výsledek se předá do šablony post_detail.html.
3. Vytvoření příspěvku:
def post_create_view(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
form.save()
return redirect(home_view)
else:
form = PostForm()
return render(request, "blog/post_form.html", {"form": form})
- Pokud je metoda požadavku
POST, vytvoříme formulář s daty odeslanými uživatelem. - Pokud je formulář validní, uložíme nový příspěvek a přesměrujeme uživatele na domovskou stránku.
- Pokud jsme na stránku přišli přes
GET, zobrazíme prázdný formulář. - Používáme šablonu
post_form.html, kterou lze využít i pro úpravy.
4. Úprava příspěvku:
def post_update_view(request, slug):
post = get_object_or_404(Post, slug=slug)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
form.save()
return redirect("post_detail", slug=post.slug)
else:
form = PostForm(instance=post)
return render(request, "blog/post_form.html", {"form": form})
- Načteme příspěvek podle slugu.
- Pokud přichází
POSTpožadavek, vytvoříme formulář s existujícím objektem a novými daty. - Pokud je vše validní, příspěvek se aktualizuje a přesměrujeme uživatele na detail článku.
- Pokud neproběhl
POST, jen zobrazíme formulář s předvyplněnými daty.
5. Smazání příspěvku:
def post_delete_view(request, slug):
post = get_object_or_404(Post, slug=slug)
if request.method == "POST":
post.delete()
return redirect("post_list")
return render(request, "blog/post_confirm_delete.html", {"post": post})
- Načteme příspěvek podle slugu.
- Pokud uživatel potvrdí smazání pomocí
POSTpožadavku, příspěvek se smaže a přesměrujeme ho na seznam příspěvků. - Jinak zobrazíme potvrzovací stránku
post_confirm_delete.html
Tento soubor views.py obsahuje kompletní logiku pro správu příspěvků v našem blogu. Každý view je přehledně oddělen a plní jasně danou roli:
home_view– přehled příspěvkůpost_detail_view– zobrazení detailu jednoho příspěvku,post_create_view– přidání nového článku,post_update_view– úprava existujícího článku,post_delete_view– smazání článku.
Kde se definují URL adresy?
Ve výchozím Django projektu najdeme soubor urls.py ve složce s názvem hlavní aplikace (často core, config, nebo dle vlastního pojmenování). Právě zde budeme definovat všechny cesty, které povedou na příslušné view funkce.
Routing – URL adresy
from django.contrib import admin
from django.urls import path
from blog.views import (home_view, post_detail_view, post_create_view, post_update_view, post_delete_view)
urlpatterns = [
path("admin/", admin.site.urls),
path("", home_view, name="home"),
path("post/new", post_create_view, name="post_create"),
path("post/<str:slug>", post_detail_view, name="post_detail"),
path("post/<str:slug>/edit", post_update_view, name="post_update"),
path("post/<str:slug>/delete", post_delete_view, name="post_delete"),
]
Co se tady děje?
1. Importy
from blog.views import ...
Importujeme všechny potřebné funkce ze souboru views.py, které jsme vytvořili dříve.
2. urlpatterns
Toto je seznam všech cest, které bude naše aplikace obsluhovat.
path('', home_view, name='home')
- Kořenová URL adresa (např.
http://localhost:8000/) - Zobrazí výpis všech příspěvků pomocí
home_view.
path('post/new', post_create_view, name='post_create')
- Cesta pro vytvoření nového příspěvku.
- Šablona
post_form.htmlbude zobrazena s prázdným formulářem.
path('post/', post_detail_view, name='post_detail')
- Dynamická URL –
<str:slug>je proměnná, která se dosadí ze slugu článku. - Např.
post/muj-prvni-claneknačte detail článku s tímto slugem.
path('post//edit', post_update_view, name='post_update')
- Slouží k editaci existujícího článku.
- Na základě slugu načte článek, předvyplní formulář
post_form.htmla po odeslání provede update.
path('post//delete', post_delete_view, name='post_delete')
- Zobrazí potvrzovací stránku pro smazání článku.
- Při potvrzení příspěvek smaže.
S tímto nastavením máme plně funkční routování pro náš blog. Všechny view funkce jsou propojeny s odpovídajícími URL adresami a připraveny přijímat požadavky od uživatelů.
@admin
1. ledna 2024