Dvojitá alchymie II

25. 10. 2013 20:46 (aktualizováno) Petr Blahoš

Podívejte se na všechny díly seriálu nebo na zdrojáky příkladu.

Vítejte u druhého dílu mého seznamování se s formalchemy. Tak šup šup, git pull. A pro ty, kdo nečetli první díl: šup šup, přečtěte si první díl. Pozor pozor, nedávno jsem upravil cestu k databázi v development.ini o úroveň výš, takže bude sdílená mezi jednotlivými kroky. Buď ji přesuňte, nebo znovu vygenerujde initialize_faapp_db development.ini.

step02

Zinicializujte si step02:

cd faapp-sample\step02
python setup.py develop
rem pokud je potřeba, udělejte novou databázi
rem ..\..\scripts\initialize_faapp_db development.ini

pserve --reload development.ini
V první řadě jsme udělali drobnou úpravu handleru top. Zjišťovat si při každém volání ORM modely je blbost. Proto jsem to přesunul do model/meta.py, a seznam modelů bude dostupný jako meta.model_names. Zadruhé, když se podíváte do step01/view/view.py na edit a saveedit, uvidíte, že ty funkce jsou skoro stejné. Proto handler saveedit ruším, jak GET, tak POST mi bude obsluhovat handler edit a teprve v něm se rozhodnu, jestli mám POST a budu validovat a ukládat, nebo jestli mám GET.

step03

A teď se konečně podíváme na nějaké to formalchemy. Jdeme na step03.

cd ..\step03
python setup.py develop

pserve --reload development.ini

Zaprvé, uděláme si vlastní Grid a FieldSet. Najdete je v model/grids.py a model/fieldset.py. Nejprve mrkněte do views/views.py. Najdete tam:

model = meta.__dict__.get(request.matchdict["model"])
grid = grids.__dict__.get(request.matchdict["model"], grids.Grid)  \
                        (model, request.db.query(model).all(), )
A velmi podobný mechanizmus pro FieldSet. Jak sami vidíte, pokud je v model.grids třída se stejným jménem, jako má zobrazovaný ORM model, použijeme ji, jinak použijeme grids.Grid.

Na Grid a FieldSet se mi nelíbí způsob konfigurování. Rád bych v base class napsal, že bude readonly, což udělám voláním configure, ale v potomkovi to musím říct znovu. No nic. Ten mechanizmus máme, na zkoušku v model.grids.Address nezobrazujeme lidi na adrese (…configure(…, exclude=[self.persons])). Teď mě ale budou zajímat trochu jiné věci.

step04

Budu chtít v tabulce u každého řádku udělat odkaz na editaci a mazání. A hned na začátek řeknu, že step04 bude slepá ulička.

cd ..\step04
python setup.py develop

pserve --reload development.ini

Jak udělat ty odkazy na editaci a mazání. První, co mě napadlo bylo, přidat do Grid-modelu 2 pole, které budou jenom předstírat, že jsou pole, ale ve skutečnosti to budou odkazy na editaci a smazání. Je to sice blbě, ale dotáhneme si to do nějakého konce, ať vidíme, jak to udělat. Vše je v model.grids Máme tam CommandLinkField, což je jenom prázdná třída, která slouží k tomu, abych řekl, jak se má renderovat. Pak je tam její renderer CommandFieldRenderer. Teď v našem base Grid přidáváme 2 pole typu CommandLinkField a taky říkáme, že default renderer pro ně je CommandFieldRenderer. CommandFieldRenderer jenom vyrenderuje odkaz na routu pojemnovanou podle jména pole, s parametrem modelem a id. Kdybychom chtěli udělat třeba routu reverse, ať už by dělala co by dělala, tak bychom si v __init__.py přidali tu routu:

    config.add_route("reverse", "/reverse/{model}/{id}", )

a do Grid bychom přidali další řádek

        self.append(formalchemy.Field("_reverse",
                      label=request.translate("Reverse"),
                      type=CommandLinkField))
A ještě bychom si museli udělat handler/view.

Nakonec upozorním na to, že musím vyžadovat, aby moje Grid vždycky dostala request, protože ho budu potřebovat k lokalizaci a ke generování url z rout.

Příště se podíváme na to, jak to udělat správně pomocí šablony, a asi se konečně zbavíme toho, že každý ORM model musí mít id jako primární klíč.

Sdílet