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

Odebírat
Upozornit na
guest
6 Komentářů
Nejstarší
Nejnovější Most Voted
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!

Frugal computing: architektura pro dobu dražší infrastruktury

Vývojáři se naučili zrychlovat dotazy, přidávat cache, škálovat služby a hlídat účet za cloud. Frugal computing začíná o jednu otázku dřív: musí se výpočet, přesun dat, volání modelu nebo uložení vůbec stát? Rostoucí spotřeba datových center a nové evropské reportování ho posouvají do návrhu architektury, dřív než do závěrečné poznámky o udržitelnosti v prezentaci.

Odysseus: PewDiePie vydal open-source AI workspace, který běží na vašem vlastním hardwaru

AI
Komentáře: 0
Felix Kjellberg, youtuber se 110 miliony odběratelů, strávil rok učením se programovat a fine-tuningem vlastních AI modelů. Výsledkem je Odysseus – bezplatný, open-source workspace pro práci s umělou inteligencí, který neposílá žádná data do cloudu. Projekt má týden, přes 61 000 hvězdiček na GitHubu a znovu otevírá otázku, komu vlastně patří váš digitální kontext.

Když Git už nestačí: jak izolovat databázový stav pro pokusy AI agentů

Gitová větev vývojářům oddělí kód, ale databáze často zůstává společná. U AI agentů je to slabé místo: rychle spouštějí migrace, mění data a zkoušejí víc cest najednou. Databázová větev jim dá vlastní pracovní prostor, jenže tím práce nekončí. Ještě je potřeba řešit citlivá data, oprávnění, životnost větve i zbytek stavu aplikace.