Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Django: Prezentace dat

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.

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

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:

TIB2012

       
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.


Pavel Dvořák

Pavel Dvořák

Autor je dlouhodobým studentem Fakulty informatiky, webový nadšenec a programátor — nejraději programuje v jazycích Haskell a Python.

Školení Google+ pro firmy

DW - Školení PPC
  • Jak využít Google+ pro firemní komunikaci a marketing.
  • Čím se liší Google+ od Twitteru a Facebooku z pohledu firemního využití.
  • Jak využít Google+ v souladu s pravidly užívání.
  • Založení Google+ Page (Stránky) krok po kroku, včetně praktických tipů.

Detailní informace o školení Google+ »

Přehled názorů

pro koho?
PMD 18. 9. 2009 12:37
Nový
├ 
Re: pro koho?
Michal Valoušek 18. 9. 2009 13:45
Nový
│
└ 
Re: pro koho?
PMD 18. 9. 2009 14:20
Nový
│
 
├ 
Re: pro koho?
Michal Valoušek 18. 9. 2009 14:33
Nový
│
 
└ 
Re: pro koho?
Pavel Dvořák 19. 9. 2009 15:21
Nový
│
 
 
└ 
Re: pro koho?
Tomáš Kafka 21. 9. 2009 01:12
Nový
├ 
Re: pro koho?
Fedor 18. 9. 2009 18:45
Nový
└ 
Re: pro koho?
Kita 5. 10. 2009 12:17
Nový
Rango: alternativa Djanga pro Ruby
Botanicus 19. 9. 2009 16:40
Nový
└ 
Re: Rango: alternativa Djanga pro Ruby
Martin Malý 19. 9. 2009 17:03
Nový
 
└ 
Re: Rango: alternativa Djanga pro Ruby
Botanicus 19. 9. 2009 17:28
Nový
Kvůli vytvoření admin.py restartovat server
hynek 26. 11. 2009 22:51
Nový
└ 
Omluva Re: Kvůli vytvoření admin.py...
hynek 26. 11. 2009 22:57
Nový
Grafika
polerok 13. 12. 2009 22:19
Nový
└ 
Re: Grafika
Pavel Dvořák 13. 12. 2009 22:27
Nový
Re: Django: Prezentace dat
Django 22. 3. 2011 14:33
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem