Szablony i wzorzec MVC - cz. II

Opublikowane przez Jarosław Zabiełło Sat, 06 Jan 2007 10:35:00 GMT

W pierwszej części wyjasniono czym jest wzorzec MVC, szablony i helpery. Pora na przyjrzenie się szablonom.

Jednym z najważniejszych kryteriów, jest podział “programista czy designer” – ma on duży wpływ na to, dla kogo szablony będą proste a dla kogo – uciążliwe czy złożone. Tzn. czy szablonami będą zajmować się programiści czy też klasyczni web designerzy nie posiadający specjalnie dużej wiedzy o programowaniu? W wypadku designera, szablony posługujące się pełnym językiem programowania mogą być nie lada wyzwaniem. Przeciętny designer posługuje się Dreamweaverem i najchętniej w ogóle by nie chciał programować. A jeśli już, to tylko w zakresie jaki jest mu potrzebny do pracy nad szablonem.

Jeśli zatem mamy zarówno zespół programistów jak i takich designerów, i o nie chcemy aby programiści musieli wszystkim się zajmować, warto wybrać taki rodzaj szablonów, który mógłby być “przyswajalny” dla designerów.

Szablony zgodne z XML.

Najbardziej skrajnym przypadkiem jest użycie takich szablonów, które są “przezroczyste” dla edytorów wizualnie wspomagających projektowanie kodu HTML, np. Dreamweaver. W tym wypadku designer przygotowuje statyczne pliki HTML za pomocą takiego edytora i oddaje go programistom aby wtłoczyli w nie życie – czyli dynamikę kodu wykonywalnego po stronie serwera.

Szablony tego typo są w 100% zgodne z XML. Logika skryptu jest zaś sprytnie ukryta w dodatkowych atrybutach tagów HTML (mówi się tu o TAL czyli tag attribute language – język atrybutów znaczników) Kod zawarty w atrybutach tagów jest ignorowany przez Dreamweavera.

Tego typu szablony, choć są wygodne dla designerów (nic nie muszą dodatkowo robić) są dosyć uciążliwe dla programistów. Są w praktyce bardziej skomplikowane niż te, które dają możliwość użycia pełnego języka. Problemem jest też trudność w generowaniu za pomocą takich szablonów kodu niezgodnego z XML, np. CSS (styli kaskadowych) . Zaletą jednak jest to, że jakakolwiek potrzeba poprawy layoutu sprowadza się do podrzucenia plików designerom. Dreamveaver nie jest w stanie zniszczyć logiki jaką pracowicie programiści dodali do atrybutów HTML. Nie trzeba na nowo za każdym razem jej dodawać.

Python

  • ZPT (Zope Page Templates) – szablony używane przez serwer aplikacji Zope.
  • SimpleTAL – tak jak ZPT, ale działające jako niezależna biblioteka, można je używać bez potrzeby instalacji Zope.
  • Kid – szablony wzorowane też na ZPT ale atrybuty wykorzystują składnię XSLT. Można też tworzyć kolejne szablony na drodze obiektowego dziedziczenia.
  • Genshi – najlepsze w swej klasie. Wzorowane na XSLT (np. można używać XPath) i szablonach Kid. Genshi potrafi kod XML jak i nie-XML. Zostały pierwotnie stworzone dla doskonałego Traca (który aktualnie migruje z szablonów ClearSilver do Genshi).

Ruby

  • MasterView – ciekawe szablony dla Ruby i Railsów. Wykorzystują pełną moc i produktywność Railsów włącznie z szablonami wzorcowymi (layouts), podszablonami (partials) oraz masą helperów jakimi dysponuje Rails. Równocześnie są przezroczyste dla Dreamweavera, więc nadają się doskonale dla designerów operujących tego typu edytorem.

PHP

  • PHP TAL jest pehapową implementacją pythonowych ZPT. Jak widać szablony używane w Zope jest źródłem inspiracji dla całej reszty. :)

Szablony uniwersalne (z uproszczonym językiem)

Jeśli nie mamy do czynienia z grupą designerów bojących się dotykać kodu, można pokusić się o użycie szablonów wykorzystujących uproszczony język programowania.

PHP

Przykładem najlepszych szablonów w tej klasie dla PHPSmarty. Posiadają dosyć wygodną składnię z może jednym wyjątkiem. Domyślne ustawienia dla wstawek kodu wykorzystują dosyć niefortunnie klamry. Sprawia to potem problem dla JavaScript. Na szczęście można to przedefiniować. Poza tym Smarty oferują bardzo wygodne modyfikatory który niczym uniksowe kaskady pipes filtrują zawartość zmiennej: {$zmienna|filtr1|filtr2}. Mają też własny cache (choć oparty tylko na systemie plików) Można też tworzyć własne komponenty(choć w ograniczonym zakresie, np. trudno je iterować w pętli z powodu kolizji nazw – PHP posiada tylko jedną, płaską przestrzeń nazw dla wszystkich funkcji)

Python

Bardzo dobrym przykładem szablonów które można by dać designerom do ręki są szablony używane we frameworku Django. Korzystają one z elementów Smarty i pythonowego Cheetah. Posiadają swoją składnię, ale bardzo prostą i wygodny sposób tworzenia kolejnych szablonów na bazie już istniejących. Tzw. w szablonach Smarty kolejne szablony są tworzone za pomocą cięcia i sklejania kawałków kodu (pliki z szablonami można “includować” do większej całości). W Django można to zrobić także na drodze obiektowego dziedziczenia. Twórcy Django wyciągnęli też lekcję ze Smartów i używają dwóch klamr, zamiast jednej, co nie powoduje kolizji z kodem JavaScript.

base.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %}szablon bazowy{% endblock %}</title>
  </head>
  <body>
  {% block content %}treść szablonu bazowego{% endblock %}
</html>
example.html
{% extends "base.html" %}
{% block title %}Szablon  example.html{% endblock %}
{% block content %}
    <h1>{{ section.title }}</h1>
    {% for story in story_list %}
    <h2>
      <a href="{{ story.get_absolute_url }}">
      {{ story.headline|upper }}
      </a>
    </h2>
    <p>{{ story.tease|truncatewords:"100" }}</p>
   {% endfor %}
{% endblock %}

Szablony Django doczekały się swoich następców/naśladowców.

  • Jinja to szablony implementujące funkcjonalność Django, ale nie są związane z samym frameworkiem. Stanowią oddzielną bibliotekę którą można używać w dowolnym kodzie Pythona. Łatwo je włączyć np. do Pylonsów.

Ruby

  • Liquid – implementacja szablonów Django w języku Ruby. Można je używać np. we frameworku Rails. Nie posiadają wszystkich djangowych cech, m.in. najważniejszej – obiektowości. Nie posiadają też wszystkich helperów jakie są w Django. Jednak pozwalają na używanie ich razem z szablonami standardowymi – ERb.

O kolejnej (w wypadku Pythona – najliczniejszej) grupie szablonów pozwalającej na pełny dostęp do języka będzie w następnej części. Dają one pełny komfort programistom klnącym na ograniczenia szablonów używających swoich własnych języków.

Tagi , , , , , , , , ,  | 3 comments

Pylons 0.9.4

Opublikowane przez Jarosław Zabiełło Sun, 31 Dec 2006 01:40:00 GMT

Wyszła nowa wersja pythonowego megaframeworka (korzysta z zewn., już istniejących bibliotek) do szybkiego budowania aplikacji webowych – Pylons. W wersji 0.9.4 dodano trochę poprawek i ulepszeń. M.in. jest nowy Routes 1.6.1, ulepszono introspekcję dla XML-RPC,Akcje kontrolerów są teraz generatorami a helpery oraz metoda _ (z gettext) generują teraz obiekty Unicodowe zamiast stringów UTF-8. Znowu Pylons znacznie wyprzedza, to co dopiero jest w powijakach dla Django.

SQLAlchemy

Coraz bardziej zaznacza się tendencja w używanych pod Pythonem ORM’ach (Pylons może korzystać z dowolnych) aby zamiast SQLObject wybierać raczej SQLAlchemy. Ten drugi jest uważany za znacznie bardziej wyrafinowany i o większych możliwościach. Na liście dyskusyjnej Pylonsów Ben Bangert pokazał jak w praktyce można używać SQLAlchemy.

Szablony

Pylons potrafi korzystać z dowolnych systemów szablonów dostępnych dla Pythona. Generalnie, popularne są dwa podejścia. Szablony pisane pod propgramistów lub pod webmasterów/designerów, którzy zajmują się samą kwestią prezentacji, wizualizacji i pracują najczęściej ze “wspomagaczami” takimi jak edytor Dreamweaver.

Dla tych drugich, polecane jest podejście albo takie jak promuje Django, czyli specjalnie uproszczony język szablonów umożliwiającym generowanie zaróno HTML jak i CSS, czy innej dowolnej treści.

Albo podejście jeszcze bardziej uproszczone (dla designerów, nie dla programistów), czyli koncepcja, jaką promują twórcy frameworka Zope. Chodzi o szablony ZPT, Kid czy Genshi gdzie logika szablonów jest dodana do atrybutów. Dzięki temu są one przezroczyste dla edytorów takich jak Dreamweaver i jeśli wymagana jest częsta konsultacja z designerami to takie podejście oszczędza ponownego, ręcznego dodawania logiki dla programistów.

Nadchodzi Mako

Moim zdaniem, znacznie lepszym podejściem jest podejście jakie oferują szablony Cheetah czy Myghty. Te drugie, są aktualnie najpoteżniejsze. Mają nie tylko duża szybkość, ale bardzo dobrze działający (lepszy od Cheetah) cache oraz łatwość do tworzenia komponentów, klocków wielokrotnego użycia.

Nadchodzi jednak coś jeszcze lepszego. Developerzy Pylonsów szykują zupełnie nowy system szablonów zwany Mako (http://makotemplates.org). Jest on wzorowany na najlepszych funkcjach jakie oferują Myghty, Cheetah, Genshi i Django. Jest też bardzo szybki.

Mako oferują wielostrefowe dziedziczenie (podobnie jak Cheetah i Django). Nie jest też wymagane tak jak w Myghty, aby wstawki Pythona (zaczynające się w szablonach Myghty od znaku procenta) zaczynały wiersz. Można wstawiać je w środku tekstu lub gdziekolwiek w ramach tagów <% kod Pythona %>.

<%inherit file="base.html"/>
<%
    rows = [[v for v in range(0,10)] for row in range(0,10)]
%>
<table>
    % for row in rows:
        ${makerow(row)}
    % endfor
</table>

<%def name="makerow(row)">
    <tr>
    % for name in row:
        <td>${name}</td>\
    % endfor
    </tr>
</%def>

Unikalne dziedziczenie dynamiczne (zmienna może określać które szablony mają być bazowymi dla innych). Szablony mogą być też buforowane. Można wygodnie filtrować dane w stylu Django (Python) czy Smarty (PHP).

<%!
    def myescape(text):
        return "<TAG>" + text + "</TAG>"
%>

Heres some tagged text: ${"text" | myescape}

Oczywiście można dowolny element szablonów keszować na wiele sposobów.

<%def name="mycomp" cache="true" cache_timeout="30" cache_type="memory">
    other text
</%def>

Pylons 0.9.4 ma już wbudowaną obsługę dla Mako. Wystarczy je ściągnąć z SVN:

svn co http://svn.makotemplates.org/mako/trunk mako

Po zainstalowaniu, jedyne co trzeba, to dodać opcję

template_engine='mako' 

do wywołania config.init_app w middleware.py.

Posted in  | Tagi , , ,  | 1 comment