.. _jinja:
========
Jinja2
========
`Jinja2`_ je šablonovací jazyk pro Python, vytvořený podle Django. Je
rychlý, bezpečný, široce používaný a nabízí sandboxové prostředí pro
zpracovávání šablon.
Proměnné
========
Proměnné mohou obsahovat atributy nebo elementy, ke kterým můžeme přistoupit pomocí tečky nebo hranatých závorek. Následující dva řádky mají stejný význam.
.. code-block:: jinja
{{ var.attr }}
{{ var["attr"]}}
Pokud proměnná nebo atribut neexistuje, vrátí se nám nedefinovaná hodnota, což při vytištění zobrazí prázdný string.
Filtry
------
Proměnné mohou být modifikovány filtry. Filtry se od proměnných oddělují
symbolem ``|`` a mohou mít volitelné argumenty v závorkách. Můžeme skládat více
filtrů za sebe, výstup prvního filtru přejde na vstup druhého. Zde je příklad
využití filtrů::
{{ var|join(", ")|capitalize }}
Komentáře
=========
Pro okomentování části kódu používejte {# Komentář #}. Toto se hodí pro hledání chyb v kódu nebo přidání důležitých informací.
Escapování
==========
Někdy je nutné, aby Jinja2 ignoroval určité části kódu, se kterými by jinak
zacházel jako s proměnnými nebo bloky. Toho můžeme dosáhnout pomocí bloku
``raw``, do kterého vložíme kód, který má být ignorován. Zde je příklad:
.. code-block:: jinja
{% raw %}
{%- for item in item_list %}
{{ item }}
{% else %}
No items found
{%- endfor %}
{% endraw %}
.. _dědění:
Dědění šablon
=============
Nejužitečnější část jazyku Jinja2 je dědění šablon. Dědění šablon nám umožňuje
vytvořit základní šablonu, která obsahuje všechny elementy naší stránky a
definuje bloky, které mohou dědické šablony přepisovat.
Rodičovská šablona
------------------
Základní šablona definuje kostru HTML dokumentu pomocí ``{% block %}`` tagů. A
**dědické šablony nám vyplní předdefinované bloky**. Takto může vypadat
jednoduchá kostra:
.. code-block:: jinja
{% block head %}
{% endblock %}
{% block body %}{% endblock %}
Dědická šablona
---------------
Dědická šablona může vypadat takto:
.. code-block:: jinja
{% extends "skeleton.html" %}
{% block head %}
{{ super() }}
index
{% endblock %}
{% block body %}
This is index
This is paragraph
{% endblock %}
To, že tato šablona rozšiřuje další šablonu, říká tag ``{% extends %}``.
Šablonovací systém, při vyhodnocování této šablony, nejprve vyhledá jejího
rodiče. Extends tag by měl být první tag, protože vše před ním se normálně
vytiskne a může způsobit zmatek. Pro přístup k šabloně v podadresáři můžeme
použít lomítko:
.. code-block:: jinja
{% extends "kostra/skeleton.html" %}
Není možné použít více bloků se stejným jménem ve stejné šabloně. Pokud by byly
dva stejně pojmenované bloky, rodičovská šablona by nevěděla, který ze dvou
bloků použít. Pokud chcete vypsat stejný blok vícekrát, můžete použít proměnnou
``self`` a zavolat jméno bloku:
.. code-block:: jinja
{% block body %}AAAA{% endblock %}
Ačka ještě jednou:
{{ self.body() }}
Je možné vyrenderovat obsah rodičovského bloku zavoláním ``super()``. To nám
vrátí obsah rodičovského bloku a ten můžeme dále rozšířit. Pro lepší
přehlednost je možné napsat jméno bloku na konec endblocku:
.. code-block:: jinja
{% block head %}
{{ super() }}
index
{% endblock head %}
V blocích nelze přistoupit k proměnným, které jsou definované v jiných vrstvách:
.. code-block:: jinja
{%- for item in item_list %}
{% block neco %}{{ item }}{% endblock %}
{%- endfor %}
Tento kód by nám vytiskl jen spoustu prázdných řádků, protože uvnitř bloku nelze přistoupit k proměnné item. Toto můžeme změnit přidáním do bloku scoped, což zpřístupní tyto proměnné v daném bloku:
.. code-block:: jinja
{%- for item in item_list %}
{% block neco scoped %}{{ item }}{% endblock %}
{%- endfor %}
Řídící struktury
================
Řídící struktury jsou věci, které řídí tok programu. Například if, elif, else,
for, macro a block. Řídící struktury se nachází uvnitř těchto závorek {% … %}.
For
---
Řídící struktury jsou věci, které řídí tok programu. Například ``if``,
``elif``, ``else``, ``for``, ``macro`` a ``block``. Řídící struktury se nachází
uvnitř těchto závorek {% … %}.
.. code-block:: jinja
{%- for item in item_list %}
{{ item }}
{%- endfor %}
Díky tomu, že proměnné v šablonách si zachovávají vlastnosti objektu, je možné
použít i slovník:
.. code-block:: jinja
{% for key, value in slov.iteritems() %}
{{ key|e }}
{{ value|e }}
{% endfor %}
Na rozdíl od jazyka Python ve smyčce nemůžeme použít break nebo continue. Ale
můžeme filtrovat seznamy, což nám umožní přeskočit dané položky. Následující
příklad přeskočí všechny skryté položky:
.. code-block:: jinja
{%- for item in item_list if not item.hidden %}
{{ item }}
{%- endfor %}
Pokud žádné opakování neproběhlo, protože je seznam prázdný nebo filtrování
odstranilo všechny položky ze seznamu, můžeme zobrazit náhradní blok pomocí
else:
.. code-block:: jinja
{%- for item in item_list %}
{{ item }}
{% else %}
No items found
{%- endfor %}
If
----------
Toto tvrzení je porovnatelné s ``if`` v Pythonu. Můžeme ho použít pro vyzkoušení, jestli proměnná je definovaná, není prázdná nebo není nepravdivá:
.. code-block:: jinja
{% if not session.logged_in %}
log in
{% else %}
log out
{% endif %}
Makra
-----
Makra jsou porovnatelná s funkcemi v jiných programovacích jazycích. Jsou
užitečné pro uložení často používaných věcí do znovu použivatelných funkcí. Zde
je příklad vytvoření makra:
.. code-block:: jinja
{% macro input(name, value='', type='text', size=16) -%}
{%- endmacro %}
Tímto způsobem můžeme makro zavolat:
.. code-block:: jinja
Firstname:{{ input("Firstname") }}
Lastname:{{ input("Lastname") }}
Nickname:{{ input("Nickname", size="12") }}
Age:{{ input("Age", type="number", size="3") }}
Password:{{ input('Password', type='password') }}
Call
----
V některých případech je užitečné předat makro dalšímu makru. Pro tento případ
tu je speciální blok ``call``. Bloku ``call`` můžeme předat argumenty. Zde je
příklad použití bloku call:
.. code-block:: jinja
{% macro Clanek(title, class='clanek') -%}
{{ title }}
{{ caller() }}
{%- endmacro %}
{% call Clanek("Nadpis") %}
Text ktery se zobrazi v promenne caller.
{% endcall %}
Importování
-----------
Jinja2 umožňuje importovat makra z jiných šablon. Je důležité si uvědomit, že
importované šablony nemají přístup k proměnným v aktuální šabloně, pokud
proměnné nejsou globální. Buď můžeme importovat celou šablonu do proměnné, nebo
jen specifická makra. Náš modul může vypadat takto:
.. code-block:: jinja
{% macro input(name, value='', type='text', size=16) -%}
{%- endmacro %}
{%- macro textarea(name, value='', rows=10, cols=40) -%}
{%- endmacro %}
Nejjednodušší je importovat celý modul do proměnné:
.. code-block:: jinja
{% import "forms.html" as forms %}
Username
{{ forms.input("autor") }}
Title
{{ forms.input("titulek") }}
{{ forms.textarea("clanek") }}
Nebo můžeme importovat jednotlivá makra:
.. code-block:: jinja
{% from "forms.html" import input, textarea %}
Username
{{ input("autor") }}
Title
{{ input("titulek") }}
{{ textarea("clanek") }}
Makra a proměnné, jejichž jména začínají jedním nebo více podtržítky jsou soukromá a tak nemohou být importována.
Testování šablon
================
Při hledaní chyb v kódu je užitečné zjistit zdrojový kód, který Jinja2 vyprodukuje z šablon. Toto můžeme zjistit následujícím způsobem:
.. code-block:: python
from jinja2 import Template
temp = Template(u'''\
titulek
{{ var|e }}
{% for item in item_list %}
{{ item }} kostek
{% endfor %}
{% for key, value in dict.iteritems() %}
{{ key|e }}
{{ value|e }}
{% endfor %}
''')
print temp.render(
var = '
neco
',
item_list = [5, 6, 13, 23, 41],
dict = {"neco":1,"jine":4, "dalsi":45},
)
Do ``Template('''…''')`` vložíme šablonu, kterou chceme otestovat a do
``temp.render()`` vložíme proměnné, které chceme, aby šablona převzala. Po
spuštění programu Python vytiskne zdrojový kód do konzole, který Jinja2 vytvoří
z šablony.