sexta-feira, 4 de janeiro de 2008

Usando modelos em Python

Quando trabalhamos com desenvolvimento web, uma coisa que facilita muito são os modelostemplates.

Modelo é um texto com o formato desejado da página – ou de um trecho dela – com «marcas» que indicam substituições – ou comandos, nos casos mais complexos.

Por exemplo:
tmpl = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="%(lang)s" lang="%(lang)s">
<head>
%(meta)s
<title>%(title)s</title>
%(css)s
<script>
%(javascript)s
</script>
</head>
<body %(bodyload)s>
<h1 class="title">%(title)s</h1>

<div id="body">
%(main)s
</div>
</body>
</html>"""


Esse modelo poderia ser processado assim:
html = tmpl % {
"lang": "pt-br",
"meta": """<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache Control" content="no-cache, must-revalidate" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
""",
"title": "Teste de modelos",
"css": "",
"javascript": "",
"bodyload": "",
"main": "Este &eacute; apenas um exemplo simples de uso de modelos"
}


No modelo, cada trecho %(…)s vai ser substituído pelo valor equivalente à chave entre parêntesis. Por exemplo, %(title)s será substituído por Teste de modelos.

Observação: como estamos usando %s, os valores precisam ser strings.

Template strings


O módulo string possui a classe Template, que oferece uma forma mais interessante de processar modelos.
from string import Template


No texto do modelo, os trechos a serem substituídos terão o formato aproximado de variáveis em shell, ou seja, $… ou ${…}.

O modelo anterior ficaria assim:
tmpl = Template("""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="$lang" lang="$lang">
<head>
$meta
<title>$title</title>
$css
<script>
$javascript
</script>
</head>
<body $bodyload>
<h1 class="title">$title</h1>

<div id="body">
$main
</div>
</body>
</html>""")


E será processado assim:
html = tmpl.substitute(
lang = "pt-br",
meta = """<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache Control" content="no-cache, must-revalidate" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
""",
title = "Teste de modelos",
css = "",
javascript = "",
bodyload = "",
main = "Este &eacute; apenas um exemplo simples de uso de modelos"
)


Uma vantagem aqui é que não é preciso que o valor seja string. Será usada automaticamente a representação string do valor.

Um exemplo rápido:
>>> from string import Template
>>> tmpl = Template("numero = $num")
>>> print tmpl.substitute(num=2.3)
numero = 2.3
>>>


HTML::Template


Um módulo mais poderoso é HTML::Template.

Além de simples substituições, com esse módulo ainda é possível fazer pequenos loops e blocos condicionais.

Assim como em DTML, os comandos são identificados por tags especiais.

A simples substituição é feita pela tag <TMPL_VAR …> (ou <!-- TMPL_VAR … -->).

Então em vez de %(title)s ou $title, usaremos <TMPL_VAR title>.

Essa tag suporta um atributo ESCAPE, que altera o valor inserido:
  • <TMPL_VAR title ESCAPE="NONE"> – nenhuma alteração;
  • <TMPL_VAR title ESCAPE="HTML"> – caracteres não-ASCII serão «escapados» como em HTML – por exemplo, & vira &amp;;
  • <TMPL_VAR title ESCAPE="URL"> – caracteres não-ASCII serão «escapados» como em uma URL – por exemplo, & vira %26.


O padrão é HTML.

Uma lista completa dos comandos pode ser encontrada na página de referência.

Nosso modelo ficaria assim:
tmpl = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<TMPL_VAR lang>" lang="<TMPL_VAR lang>">
<head>
<TMPL_VAR meta ESCAPE="NONE">
<title><TMPL_VAR title></title>
<TMPL_VAR css ESCAPE="NONE">
<script>
<TMPL_VAR javascript ESCAPE="NONE">
</script>
</head>
<body <TMPL_VAR bodyload ESCAPE="NONE">>
<h1 class="title"><TMPL_VAR title></h1>

<div id="body">
<TMPL_VAR main>
</div>
</body>
</html>"""


E para processá-lo:
from htmltmpl import TemplateManager, TemplateProcessor

tproc = TemplateProcessor()

tproc.set("lang", "pt-br")
tproc.set("meta", """<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache Control" content="no-cache, must-revalidate" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
""")
tproc.set("title", "Teste de modelos")
tproc.set("css", "")
tproc.set("javascript", "")
tproc.set("bodyload", "")
tproc.set("main", "Este é apenas um exemplo simples de uso de modelos")

html = tproc.process(TemplateManager().prepare(tmpl))


No manual sobre a versão Python você pode encontrar alguns outros exemplos interessantes, inclusive usando MySQL-Python.

Observação: uma forma fácil de instalar MySQL-Python é usando EasyInstall:
bash$ easy_install -U python-mysql



Peço desculpas pelo artigo um tanto corrido, mas a ideia foi simplesmente demonstrar formas diversas de uso de modelos.

[]'s
Cacilhas, La Batalema
blog comments powered by Disqus