Sbíráme objednávky
Na konci zdrojového textu šablony index_html jsou dvě položky s poněkud nestandardní syntaxí z hlediska HTML; položka name= totiž obsahuje dvojtečku a klíčové slovo records.
Nejprve je třeba si uvědomit, že tato „úchylka“ nemá nic společného s jazykem šablon ZPT. Není totiž uvedena v rámci prefixu tal:. Z hlediska této šablony je to prostě kód HTML, který je vstupem pro skript addItems. Ten je uvedenen v zahajovacím zaklínadle formuláře <form action=„addItems“>. Záleží tedy na tomto skriptu, co si počne s proměnnými, které se jmenují orders.id:records a orders.quantity:records.
Abych řekl pravdu, nejsou to žádné čáry. Samotné HTML prostě nemá datové struktury typu pole. To znamená, že potřebujeme-li generovat předem neznámý počet značek typu <input…>, museli bychom značky uměle dynamicky číslovat (order1_id, order2_id atd.) a zpětně je rozkládat v přijímacím skriptu. To je pracné a Zope se snaží pracné úkoly eliminovat. Nazveme-li naše proměnné podle syntaxe <proměnná>.<atribut>:records, bude práce s výsledkem snadná, což si ukážeme v popisu skriptu addItems.
Skript addItems
Skript addItems se postará o uložení nových objednávek do košíku. Použije k tomu subsystém pro řízení sezení. V devátém dílu tohoto seriálu jsem psal o vypalování cejchu webovému prohlížeči pomocí cookie. Díky tomuto označkování, které provede Zope zcela automaticky1, můžeme uchovávat libovolné údaje na serveru, přičemž tyto údaje jsou svázané s původním klientským (ocejchovaným) webovým prohlížečem. Této operaci se říká Řízení relace (Session Management). Každý prohlížeč, který otevře vaše dynamické stránky v Zope, má svůj cejch a na serveru jsou jeho jménem uchovávány údaje v jeho vlastní relaci – tedy v jeho vlastní schránce, vybudované automaticky a bez ohledu na to, zda má na vašem serveru účet. Relace tedy slouží i tzv. anonymním uživatelům.
Ukládání a načítání dat relace se provádí pomocí objektu REQUEST.SESSION. Na začátku skriptu addItems vidíte načítání obsahu relace v praxi:
session=context.REQUEST.SESSION
items=session.get('items',{})
Metoda get(‚items‘,{}) vrátí položku itemsuloženou v relaci a zapíše ji do proměnné items skriptu. Na začátku, čili když je košík prázdný, ale položka items v relaci vůbec neexistuje. Požehnaná metoda get v takovém případě vrátí prázdný slovník, tedy {}. Máme tak postaráno o inicializaci proměnné items skriptu. Tato syntaxe je použita ve skriptu addItems ještě jednou.
for order in orders:
quantity=int(order.quantity)
if quantity != 0:
items[order.id]=items.get(order.id, 0) + quantity
Ve výše uvedeném zdrojovém textu už probíhá zpracování objednávek. V iteraci vidíme, že formulářová položka orders:records z předchozí kapitoly se používá opravdu snadno, protože je přímo dostupná pro skript addItems bez nutnosti jakéhokoliv explicitního přenosu. Stačí uvést ji jako parametr skriptu. Po spuštění iterace se musíme vyrovnat s tím, že v relaci se vše ukládá jako typ řetězec. To se nehodí pro proměnnou quantity, a tak je převedena na celočíselný typ. Když je výsledek operace nenulový, přičte se quantity (množství) k už objednanému množství stejného zboží.
Pokud máte cit na bezpečnostní rizika, určitě vás napadne, že by bezcitný zákazník mohl zadat záporné množství. Trefa! Skript není na takovou situaci připraven a připustí objednávku záporného množství zboží.
session['items']=items
if REQUEST is not None:
return container.index_html(REQUEST)
Na závěr uložíme nový stav proměnné items do položky items a zavoláme znovu šablonu index_html.
Předpokládám, že si činnost košíku už dávno zkoušíte v praxi. Abyste viděli více do vnitřností relace, neškodilo by průběžné zobrazování obsahu relace. To lze snadno zařídit. Stačí, když někam do šablony index_html přidáte buď zobrazení relace pomocí cesty request/SESSION2, nebo rovnou zobrazíte celý požadavek pomocí cesty request. Chcete hotový funkční příklad a radu pro vhodné umístění? Vložte následující text těsně před značku </div>.
<hr>
<p tal:content="request/SESSION"></p>
<hr>
<p tal:content="structure request"></p>
1 Za předpokladu, že máte v kořenové složce Zope instanci typu Session Data Manager. To je v čerstvé instalaci Zope splněno.
2 Všimněte si, že ve skriptech Python se pro REQUEST.SESSION používají velká písmena, kdežto v jazyce šablon ZPT se musí psát <p tal:content=„request/SESSION“>. Nepopleťte to, jinak se objeví zmatené chybové hlášení o neexistenci požadovaného klíče. Kéž by jednotlivé technologie Zope byly konzistentnější, lidé na sebe hodnější a dívky povolnější!