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

Zdroják » Různé » web.py – šablonovací systém

web.py – šablonovací systém

Články Různé

Šablonovací systém je důležitou součástí webového frameworku, proto se dnes budeme věnovat šablonovacímu systému web.py – Templatoru. Vypíšeme si hlavní konstrukce, řekneme si něco o slučování šablon a vše si předvedeme na příkladech.

V minulém díle jsme se věnovali základům vývoje aplikací ve frameworku web.py, především pak komponentě controlleru. V dnešním díle se budeme věnovat jiné důležité komponentě, a to pohledům (views), které zajišťují vykreslování uživatelského prostředí. Povíme si o šablonovacích systémech Pythonu, konstrukcích známých z prostého Pythonu a slučování šablon.

Templetor

Součástí web.py je šablonovací systém Templetor. Jeho syntaxe je velice podobná (takřka totožná) syntaxi Pythonu, jeho ovládnutí je tedy otázkou několika chvil. Pokud chcete raději používat šablonovací systémy jako Jinja2 nebo Cheetah, i ty lze po krátké konfiguraci ve web.py používat.

Pokud chcete Templetor v aplikaci použít, je nutné jej nejdřív nakonfigurovat. Do hlavního souboru aplikace stačí přidat render a jako parametr mu předat složku obsahující šablony:

render = web.template.render('templates')

Funkce vykreslující šablonu může vypadat například takto, tečkovou konvencí zde určíme její umístění ve složce šablon:

return render.informace.kontakt()

Samotná šablona je soubor s koncovkou html, v němž do obyčejného HTML kódu vkládáme konstrukce Templatoru.

Proměnné

Přístup k proměnným (a funkcím) aplikace je v Templatoru standardně omezen pouze na proměnné předané při vykreslení šablony. Díky tomu je aplikace od šablon maximálně oddělena.

Pokud předáváme proměnnou aplikace šabloně:

return render.informace.kontakt("Petr", "Letovice")

je třeba na začátku šablony určit přijímané proměnné (ve správném pořadí) a jejich názvy:

$def with (jmeno, mesto)

K proměnným lze poté přistupovat hned několika způsoby:

$jmeno
${jmeno + ' ' + mesto}
$slovnik[klic].funkce('argument'). 
$(promenna)nanana.

Pro přiřazování hodnot do proměnných lze použít následující konstrukci:

$ promenna = (10 / 5) * 3

Templator standardně filtruje „nebezpečné“ znaky, které by mohly ovlivnit šablonu, pokud tedy necháte vypsat 1 < 2, systém vyrendruje 1 &lt; 2. Pro vypnutí filtru stačí při vypisování namísto $promenna použít $:promenna.

Protože je znak dolaru $ využit pro syntaxi, pro vypsaní samotného znaku budete muset použít $$.

Globální proměnné

Pokud chcete šablonám zpřístupnit nějakou proměnnou či funkci z aplikace, stačí při tvorbě renderu předat do proměnné globals slovník.

render = web.template.render('templates', globals={'funkce':funkce_aplikace,'promenna':promenna_aplikace})

Komentáře

Pro zapsání komentářů stačí na začátek řádku přidat $#. Tento kód se potom neobjeví ve výsledném HTML.

$# komentář kódu šablony

Větvení

Větvení kódu zde funguje takřka stejně jako v samotném Pythonu. Stačí zapsat $if, $elif či $else, podmínku a za dvojtečku už samotný kód. Nezapomeňte stejně jako v Pythonu, odrážet kód bloků.

$if 1 < 2:
    Jedna je menší než dvě.
$else:
    Jedna je větší nebo rovno dvěma.

Kód lze psát i do jednoho řádku:

$if 1 < 2: Jedna je menší než dvě.

Cykly

Pro cyklení zde slouží $for a $while, zápis je podobný jako u větvení:

$for i in range(10): 
    Číslo $i

$while podminka:
    Žluťoučký kůň úpěl.

Z objektu loop můžete získat proměnné určující stav procházení cyklem, to se může hodit například při práci s tabulkami:

loop.index: počet projití cyklu (začíná 1)
loop.index0: počet projití cyklu (začíná 0)
loop.first: True pokud jde o první projití
loop.last: True pokud jde o poslední projití
loop.odd: True když jde o liché projití
loop.even: True když jde o sudé projití
loop.parity: vrací odd pri lichém projití a even při sudém
loop.parent: vrací vnější smyčku

Funkce

V šabloně je možné díky $def definovat i samotné funkce:

$def pozdrav(jmeno):
    Ahoj $jmeno

$pozdrav("světe")

Samotný kód

A konečně, do šablon lze pomocí $code zapisovat čistý kód Pythonu:

$code:
    x = 2
    for i in range(4):
        x = x * x

    def funkce():
        ...
        ...

Z bezpečnostních důvodů ale není možné využívat exec, importy, přistupovat k atributům začínajících podtržítkem _ a používat vestavěné funkce jako open, getattr, setattr a podobně.

Základní šablona

Aby nebylo nutné v každé šabloně opakovat kód hlavičky, menu, patičky apod., je možné vytvořit základní šablonu, do které se budou další šablony vnořovat. Soubor základní šablony určíme při vytváření renderu pomocí atributu base:

render = web.template.render('templates', base='base')

Základní šablona by pak mohla vypadat například takto, proměnnou content určujeme místo, na které se má vložit obsah dalších šablon, proměnnou titulek získanou z objektu content využijeme pro vypsání titulku stránky:

$def with (content)

<html>
<head>
    <meta charset="utf-8">
    <title>$content.titulek</title>
</head>
<body>
$:content
</body>
</html>

Kód vnořené šablony by mohl vypadat takto, pomocí $var zde definujeme proměnnou titulku, jako content se použije zbytek šablony:

$var titulek: Nadpis stránky

<h1>Ahoj Světe</h1>

Poté už stačí jen použít použít render k vykreslení stránky.

Seznamy v proměnných

Pokud chcete vkládat celé seznamy proměnných (například adresy CSS souborů), není nutné je definovat jednotlivě. Stačí do proměnné v podšabloně zapsat seznam hodnot oddělený mezerami:

$var csssoubory: style.css fonty.css

<h1>Ahoj Světe</h1>

V hlavní šabloně pak proměnnou rozdělíme do seznamu a ten necháme pomocí cyklu vypsat:

$def with (content)

$if content.csssoubory:
    $for c in content.csssoubory.split():
        <link rel="stylesheet" href="$c" type="text/css"/>

Statické soubory

Protože nelze z vnějšku přistupovat k souborům aplikace, je nutné pro statické soubory (jako jsou kaskádové styly, obrázky, JavaScript) vytvořit složku static. K souborům z této složky lze poté přistupovat na adrese /static/nazev-souboru.css.

Příklad aplikace

V dnešním příkladu budeme vycházet z aplikace vytvořené minule. Upravíme úvodní stránku, která zatím pouze vrací text „Ahoj“.

Nejdříve přidejte do projektu složku templates a v ní vytvořte soubor základní šablony base.html:

$def with (content)

<html>
<head>
    <meta charset="utf-8">
    <title>$content.titulek</title>
    <style>
        body {
            background-color: #DEFCD7;
        }
    </style>
</head>
<body>
$:content
</body>
</html>

Dále vytvořte šablonu úvodní strany uvod.html:

$var titulek: Úvodní strana

<h1>Ahoj Světe</h1>

Nyní otevřete základní soubor aplikace main.py, přidejte render a pozdrav „Ahoj“ nahraďte vykreslením šablony:

# -*- coding=utf-8 -*-
import web

urls = (
    '/','Uvod',
    '/umocni/(\d+)', 'Umocni',
)

app = web.application(urls, globals())
render = web.template.render('templates', base='base')

class Uvod:
    def GET(self):
        return render.uvod()
class Umocni:
    def GET(self, cislo):
        return int(cislo) * int(cislo)

if __name__ == "__main__":
    app.run()

Nakonec si můžete aplikaci pustit, při otevření adresy http://localhost:8080/ by se měla zobrazit stránka s pozdravem v nadpisu.

Závěr

To je pro tento díl vše. Příště se budeme věnovat databázím, autorizaci a autentizaci uživatelů.

Komentáře

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

Nikdy jsem nepochopil, proč většina frameworků používá pro jednoduchý výpis proměnné poměrně složitou syntaxi jako Jinja {{ foo }}, Mako ${name}.

Proti tomu obyčejné $name v templatoru je geniálně jednoduché a o 2 až tři znaky kratší. (A takové PHP-intuitivní, vždyť vlastně i to PHP je (mělo být) spíš šablonovací systém, než programovací jazyk :-) )

Opravdu by mne zajímalo, co autory většiny frameworků vede k tomu volit tak složitou syntaxi?

diverman

Proc se ptas zde a nezeptas se autoru?

Jakub Kulhan

Důvod bych viděl v zjednodušení implementace – ať už vývojář sprcá template engine pár regulárními výrazy, nebo použije opravdový lexer a klon YACCu, když je jasně určený levý a pravý delimiter, snadněji se to parsuje. A že jsou zrovna tolik oblíbené kudrnaté závorky, je tím, že se v HTML moc nevyskytují.

Lamicz

Protoze nestačí jenom $var, ale je potřeba htmlspecialchars($var, ENT_QUOTES);

golf

Jde spíš jen o syntaxi, Python se dá všelijak přiohnout.

Viz třeba způsob jakým Templetor volá konkrétní šablonu render.informace.kontakt() namísto obvyklého render("informace/kontakt.html"). Konkrétně za tímto musí být „nadbytečný“ kód navíc, který pomocí getattr slepí cestu k šabloně, ale to by snad nemuselo až tak vadit, při použití dobrého cachování.

Trochu jsem se chtěl na web.py podívat, ale verze pod Python 3 zlobí, respektive řekl bych, že vůbec není udělaná, jsou tam nefunkční importy. Zkoušel jsem to opravit, ale vzdávám to. Škoda, docela zajimavý framework.

tomas

Díky za další díl o web.py frameworku. Mám jen dva hnidopišské postřehy :-)

  • v odstavci „Základní šablona“ ve větě „…proměnnou title získanou z objektu content využijeme pro vypsání titulku stránky“ by vzhledem k dalšímu kódu měl být název proměnné titulek;
  • v odstavci „Seznamy v proměnných“ sladit názvy souborycss a csssoubory.

Ale jinak dobrá práce!

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.