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 Meta třídě určíme, že budeme pracovat s modelem Post a že chceme zobrazit pouze pole title a body.
  • Pomocí labels upraví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
  • render slouží k vykreslení HTML šablon s daty.
  • get_object_or_404 zjednodušuje získání objektu z databáze – pokud nenajde, vrátí automaticky 404.
  • redirect přesměruje uživatele na jinou stránku.
  • Dále importujeme náš model Post a 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í POST pož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í POST pož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.html bude 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-clanek nač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.html a 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ů.

Michal Šanda

13. května 2025


Komentáře 0