Přejít k navigační liště

Zdroják » Různé » Django: Prezentace dat

Django: Prezentace dat

Články Různé

Projekt jsme na konci minulého dílu zanechali ve stavu, ve kterém správci mohou pohodlně upravovat data z našich databázových modelů. Nyní se naučíme, jak tato data prezentovat návštěvníkům webu.

Pod pojmem prezentace dat si můžeme představit spojení pohledu a šablony, při kterém zpracováváme data a zobrazujeme je ve vhodné formě uživatelům. Nejprve si ukážeme několik důležitých vlastností šablonovacího systému.

Strukturování šablon

Když jsem kdysi dávno začal s vytvářením HTML stránek a neuměl pořádně programovat v žádném jazyce, nejhorší ze všeho pro mě bylo zamezit opakování základního kódu, např. obsahu značky <head>, navigace nebo patičky. Jakákoliv změna na stránkách znamenala otevřít všechny „postižené“ soubory a opravit opakující se kusy HTML kódu. Tehdy jsem na to použil rámy, což se časem ukázalo jako naprostý krok vedle. Teď můžu v Djangu stejný problém jednoduše vyřešit použitím značek šablonovacího systému {% block %} a {% extends %}.

Princip si ukážeme na příkladu — nejprve si vytvoříme základní šablonu pro web videopůjčoven. Tento soubor bývá zvykem pojmenovávat base.html a je potřeba ho uložit do adresáře templates:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>{% block title %}Videopůjčovny s. r. o.{% endblock %}</title>
<link rel="stylesheet" href="{{ MEDIA_URL }}css/style.css" type="text/css">
</head>

<body>
<div id="header">Videopůjčovny s. r. o.</div>
<div id="menu">
<ul>
<li><a href="/">Titulní strana</a></li>
<li><a href="/provozovny/">Provozovny</a></li>
<li><a href="/nabidka/">Nabídka titulů</a></li>
<li><a href="/kontakt/">Kontakt</a></li>
<li><a href="/pro_cleny/">Pro členy</a></li>
</ul>
</div>
<div id="content">{% block content %}{% endblock %}</div>
</body>
</html>

Pomocí značky {% block %} si označíme místa, kam se budou vkládat bloky kódu pro jednotlivé stránky. V našem případě to je titulek stránky (title) a její obsah (content). Text uvedený uvnitř značek v titulku je výchozí text bloku. Na začátku šablony je též uvedena proměnná {{ MEDIA_URL }}, která obsahuje cestu ke statických souborům. Poskytuje nám ji takzvaný kontextový procesor django.core.context_processors.media. Kontextové procesory se využívají v situacích, když potřebujeme dostat do více šablon společné proměnné.

Co se týče pojmenování, je vhodné (hlavně ve větších projektech) dodržovat zavedené konvence.

Dále si vytvoříme šablonu pro titulní stranu. Ta využije (rozšíří) základní šablonu a přepíše bloky svým vlastním obsahem. Pojmenujeme ji třeba front_page.html a uložíme ji také do adresáře templates:

{% extends "base.html" %}

{% block content %}
<h1>Dobrý den!</h1>

<p>Vítáme vás na webu naší sítě poboček videopůjčoven.</p>
{% endblock %}

Na prvním řádku jsme pomocí značky {% extends %} uvedli, že chceme rozšířit šablonu base.html. V bloku title jsme nechali výchozí text, obsah bloku content byl nahrazen za uvítací blábol. Podobně to budeme dělat i u ostatních šablon.

Generické pohledy

Nejlepší kód je ten, který nemusíme psát. To je důvod, proč nám tvůrci Djanga dali k dispozici několik pohledů, jež dělají naprosto obecné věci — kupříkladu přidání, úpravu nebo zobrazení objektu, a proto se jim říká generické pohledy. Můžeme je nalézt v modulu django.views.generic a zkusíme si použít nejjednodušší z nich, simple.direct_to_template, který pouze zobrazí šablonu.

Tento pohled stačí přidat mezi URL (do souboru urls.py v adresáři projektu) a jako parametr poskytnout slovník obsahující klíč template:

urlpatterns += patterns('',
    (r'^admin/', include(admin.site.urls)), # Django 1.0: (r'^admin/(.*)', admin.site.root),
    (r'^$', 'django.views.generic.simple.direct_to_template', {'template': 'front_page.html'}),
)

Když nastartujeme vývojový server (python manage.py runserver) a přejdeme na adresu http://127.0.0.1:8000/, můžeme vidět titulní stranu webu videopůjčoven:

Django 6

Místo generického pohledu jsme si v souboru video_store/views.py mohli vytvořit takovou funkci:

from django.shortcuts import render_to_response
from django.template import RequestContext

def front_page(request):
    return render_to_response('front_page.html', {}, context_instance=RequestContext(request))

Jediné co je tu nové, je zavolání funkce RequestContext(request), což nám zpřístupní výchozí kontextové procesory, abychom mohli v šabloně využít proměnnou {{ MEDIA_URL }}. Tento pohled bychom museli stejně přidat do URL, takže používání generických pohledů je mnohem úspornější a elegantnější. Proto si vyzkoušíme použít ještě další, na výpis provozoven. Opět si nejdříve vytvoříme šablonu (templates/stores.html):

{% extends "base.html" %}

{% block content %}
<h1>{% block title %}Provozovny{% endblock %}</h1>

{% for object in object_list %}
  <h2>{{ object.store }}</h2>

  <ul class="store">
  <li>{{ object.address }}</li>
  <li>{{ object.city }}</li>
  <li>{{ object.postal_code }}</li>
  {% if object.email %}
    <li><a href="mailto:{{ object.email }}">{{ object.email }}</a></li>
  {% endif %}
  </ul>

  {% if object.description %}
    <p>{{ object.description }}</p>
  {% endif %}
{% endfor %}
{% endblock %}

Především je tu použit jednoduchý trik, který nám zobrazí v titulku stránky stejný text jako v nadpisu, aniž bychom ho museli psát dvakrát. Dále zde můžeme vidět dvě nové značky, {% for %} a {% if %}. První se podobá for cyklu z Pythonu, do proměnné object přiřadí aktuální prvek ze seznamu object_list. Druhá značka je hodně podobná pythonovému větvení if, až na to, že nepodporuje větev elif.

Proměnná object_list bude obsahovat seznam provozoven. Výchozí pojmenování této proměnné je možné změnit, podobně jako další parametry, viz dokumentaci.

V tomto kódu tedy vypíšeme postupně všechny provozovny a jejich adresy. Pokud je zadána e-mailová adresa, vypíšeme i tu. V opravdovém projektu bych se ji snažil nějakým způsobem ochránit před spamery, třeba pomocí JavaScriptu. Jestliže je u pobočky vyplněný popis, vypíšeme ho také. Znova budeme muset provázat šablonu přes generický pohled s adresou (soubor urls.py), tentokrát je to trochu složitější, protože musíme specifikovat i výběr dat:

from hrajeme_si.video_store.models import Store

stores = {
    'queryset': Store.objects.all(),
    'template_name': 'stores.html',
}

urlpatterns += patterns('',
    (r'^admin/', include(admin.site.urls)), # Django 1.0: (r'^admin/(.*)', admin.site.root),
    (r'^$', 'django.views.generic.simple.direct_to_template', {'template': 'front_page.html'}),
    (r'^provozovny/$', 'django.views.generic.list_detail.object_list', stores),
)

Z důvodů zpřehlednění jsem si definoval proměnnou stores, místo toho, abych slovník vkládal přímo do parametru. Generický pohled list_detail.object_list požaduje klíč queryset, což je klasický QuerySet — vybrali jsme všechny záznamy z tabulky modelu Store. Změna oproti předchozímu generickému pohledu je v tom, že se klíč s názvem šablony nejmenuje template, ale template_name. Výsledek našeho snažení vypadá takto:

Django 6

Pro úplnost si ještě ukážeme, jak by to vypadalo bez použití generického pohledu:

from django.shortcuts import render_to_response
from django.template import RequestContext
from hrajeme_si.video_store.models import Store

def stores(request):
    return render_to_response('stores.html', {'object_list': Store.objects.all()},
                              context_instance=RequestContext(request))

Generické pohledy doporučuji používat všude kde to jen jde, vyhnete se tak jednotvárnému opakování kódu. Jedná se o jednoduché výpisy položek, jejich kategorizace podle data, přesměrování stránek a základní práci s formuláři. K tomu se dostaneme v pozdějších dílech seriálu.

Související odkazy

V příštím díle navážeme na toto téma a zkusíme si vytvořit složitější pohledy.

Komentáře

Subscribe
Upozornit na
guest
16 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
PMD

Tak přemýšlím, pro koho tyhle články vlastně jsou… Kdybych základy Djanga dopředu neznal, čuměl bych na to jak tele na vrata. Protože je ale znám, nedovídám se tu nic nového.

Michal Valoušek

Clanky by mely seznamit zacatecniky se zakladnimi vlastnosti Djanga.

Pokud Vam pripada jejich forma spatna, muzete obsah ovlivnit. Kazdy tyden Pavel Dvorak na IRC kanalu #django-cs (http://botland.oebfare.com/…r/django-cs/) vystavi dalsi dil serialu a ceka na pripominky z komunity. Budeme radi, kdyz se do diskuze zapojite a posunete kvalitu clanku vys.

PMD

Není to pro začátečníka moc chaotické? Jsem si vědom, že každý se učí jinak, ale možná by bylo lepší nejdřív stručně vysvětlit princip, pak příklad použití a potom ukázku kódu… Z trochou nadsázky: tady na mě nejdřív vychrlí nějaké divné značky, pak reálný příklad rovnou zmixovaný s generic views a nakonec z kontextu snad pochopím, že django má šablonovací systém a že jsme jej právě použili. Snaha o stručnost…?

Michal Valoušek

Diky za reakci.

Zkuste po nedeli sledovat zminovane IRC a pridejte svou trosku do mlyna behem pripominkovani dalsiho dilu. Cim vice oci to uvidi a vyjadri svuj nazor, tim bude serial na Zdrojaku kvalitnejsi.

keff

Ja jsem pripad uvedeny v druhem odstavci (php a drupal, predtim jsem si napsal vlastni maly cms), a forma clanku mi naprosto vyhovuje – zadne dlouhe zdrzovani, ukazka z realneho sveta, hodne kodu, a z uz uverejnenych par dilu by sel postavit maly editovatelny web… Za sebe tleskam a dekuji, behem par desitek minut jsem si udelal dobrou predstavu k cemu je Django dobre.

Fedor

napriklad pre mna ;)

Kita

No pro tebe urcite ne.

Botanicus

Pokud mate radi Django, ale preferujete Ruby pred Pythonem, muzete se podivat na Rango, ktere je Djangem inspirovane. Napriklad dnes zminovana template inheritance je v Rangu obsazena take (pokud se nemylim, je Rango jediny Ruby framework ktery ji implementuje, jinde jsou ponekud primitivni layout + view).

Jinak je Rango velmi lightweight, snazi se byt as agnostic as possible (bude funguje s libovolnym ORM, template engine etc), plne postavene na Racku, ktery na rozdil od vetsiny frameworku nijak nezakryva, ale naopak vybizi k jeho intenzivnimu pouzivani. Duraz kladu na dobrou dokumentaci (pracuje se na ni), 100% test coverage (opet in progress) a na to, aby to hlavne fungovalo a nikomu to do niceho blbe nekecalo (tj. convention over configuration ano, ale nesmi to byt na ukor konfigurovatel­nosti).

Podotykam ze je ve fazi intenzivniho vyvoje a ne vse funguje jak by melo, ne vse je zdokumentovane a ne vse je podporovane. Zacatkem noveho roku ocekavam finalni verzi 1.0.

– Source: http://github.com/botanicus/rango
– Dokumentace: http://wiki.github.com/botanicus/rango

PS: kdyby to treba nekoho zaujalo a chtel pomoct s vyvojem, muzete forknout na GitHubu pripadne commit access davam za prvni prijaty patch.

Martin Malý

Nechcete o tom napsat článek, nebo aspoň zprávičku? Ozvěte se na redakce@zdrojak.cz Díky.

Botanicus

Dekuji za nabidku Martine, clanek urcite zvazim, ale nejdrive chci aby to bylo stabilni a zdokumentovane, takze nejdrive nekdy zacatkem pristiho roku. Zpravicku napisu, nejdriv chci ale udelat tutorial a nejaky screencast aby zajemci meli vubec kde zacit.

hynek

Po vytvoření souboru admin.py je nutné restartovat vývojový server (python manage.py runserver), jinak si server souboru nevšimne. (django 1.1.1)

Zkusil jsem všechno možné, včetně odhlášení a přihlášení, stažení kompletní sbalené ukázky, čtení jiné dokumentace, všechno marné.

Kromě tohoto je popis od počátku kurzu naprosto dostatečný, krásně jednoduchý a přehledný.
Děkuji.

hynek

Promiňte. Komentář patřil k minulému dílu.

polerok

Nejprve bych chtel podekovat za „serial“, je velmmi pekne zpracovany a krasne se podle neho uci.
Nicmene se mi nedari rozchodit generecke pohledy a chtel bych se zeptat, jestli to muze mit neco spolecneho s tim, ze jedu pod win 7? Dekuji za odpoved.

Django

Podle me je clanek moc dobre napsany, lepsi cesky clanek na netu urcite nenajdete. Ja jsem si podle tohoto udelal kompletni administracni rozhrani i se strankama behem 3 dnu. A s Pythonem jsem pred tim nemel zadne zkusenosti;-) Je jasne, ze ten kdo se neorientuje ve webovych technologii to nepochopi napoprve. Ovsem to je ve vsech oborech stejne;-)

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.