Podívejte se na všechny díly seriálu nebo na zdrojáky příkladu.
Minule jsem sliboval to _ na lokalizaci. Ale lokalizace se ve FormAlchemy ukázala trošku složitější, než se na první pohled zdálo, proto se dnes budu věnovat něčemu jinému. Ale zajímavějšímu.
Ve všech pythonových webových frameworcích, se kterými jsem se setkal, se na to, abychom se z URL dostali kód, který něco udělá, používal koncept URL dispatch/routing. Tedy, pokud (relativní) url začíná články/ a potom je číslo, a router má správné pravidlo, tak nás dovede k tomu správnému handleru. Když se ale vrátíme na začátek, tak webové stránky vlastně byly skutečně fyzicky soubory na disku v nějaké hierarchii, a webový server je dával uživateli na základě cesty v url. Vlastně se nemusíme vracet na začátek, ten koncept stále na mnoha místech funguje.
Pyramid kromě URL dispatch, které jsme až dosud používali, umí i takzvaný traversal, který si vzal inspiraci právě z adresářové struktury. Do Pyramid přišel ze Zope. Traversal nepracuje s adresáři, ale s objekty.
Příklad: /blogs/2013/03/12/jmeno-clanku
Celé to traverzování začne nějakým root objektem, který bude náš aktuální kontext. Toho se zeptáme: máš blogs? On odpoví ano, a tady je. To bude teď aktuální kontext. Zase se aktuálního kontextu zeptáme: Máš 2013? Odpoví nám ano, tady je. To bude náš nový aktuální kontext, zase se ho zeptáme: Máš 03, a tak dále, až dojdeme na konec, nebo až nám někdo řekne nemám. Tak předpokládejme, že máme kontext. V URL dispatch jsme řekli, jaké route patří handler. U traversalu nemáme routy, tak říkáme, jakému contextu patří handler. Důkladněji je to popsané zde.
Já si budu chtít vytvořit takovou strukturu, že na / najdu seznam modelů. Kliknitím na model se dostanu na url /Jmenomodelu, které mi zobrazí seznam objektů/záznamů/řádků tabulky s odkazy pro editaci a smazání. Odkaz pro editaci bude: /Jmenomodelu/primarniklic a odkaz na mazání /Jmenomodelu/primarniklic/delete, přičemž primární klíč bude sekvence dvojic sloupec=hodnota – urlencoded. Ještě pro vytvoření nového záznamu: Jmenomodelu/new. Traversal začíná s Root Resource. Pokud je url /, tak se traversal dál než k Root Resource nedostane. Pokud tam něco je, tak se v aktuálním contextu volá __getitem__. Nějak takhle (značně zkráceno):
class TopContext(object): # ... def __getitem__(self, name): return ModelContext(self, name) class ModelContext(object): # ... def __getitem__(self, name): if "new"==name: return NewItemContext(self) params = urlparse.parse_qs(name) q = self.request.db.query(self.model) for i in get_pk_columns(self.model): q = q.filter(i==params[i.name][0]) return ItemContext(self, q.one()) class NewItemContext(object): # ... class ItemContext(object): # ...V Top Contextu hledám model, v Model Contextu hledám konkrétní položku/řádek/objekt. V (New) Item Contextu už nehledám nic. Celé to najdete ve step09 ve model/resources.py.
Protože nemáme routy, tak nemůžeme generovat url pomocí request.route_url. Místo něj máme request.resource_url, které nám vygeneruje url pro danou resource. Resource ale musí být location-aware. To znamená, že resource má 2 property: __name__ a __parent__. To generování url si představuju tak, že se jde od aktuální resource přes __parent__ nahoru až k rootu a cestou se sbírají __name__. route_url má ty parametry, které byste asi tak čekali, třeba ocas, který se přidá k vygenerovanému url, nebo query string. Příklady uvidíte třeba v templates/formalchemy/grid_readonly.mako, kde přidáváme právě ten ocas kvůli generování odkazu na editaci a mazání.
Tak a teď už:
# nezapomeňte git pull cd step09 python setup.py develop pserve --reload development.iniČeho si všimnout?
Zatím mi traversal nepřináší nějakou výhodu, ale příště si ještě trochu pohrajeme. Mám na mysli něco, co by se mi s routingem dělalo špatně, jestli by to vůbec šlo, ale s traversalem to jde bez problémů.
Jmenuju se Petr Blahoš. Programuju něco přes 20 let. Tady se snažím psát hlavně o Pythonu, webovém frameworku Pyramid, a občas i o něčem úplně jiném.
Přečteno 19 231×
Přečteno 11 855×
Přečteno 9 354×
Přečteno 8 812×
Přečteno 8 599×