Helpers YATL¶
Considere o seguinte código em um ponto de vista:
[[=DIV('this', 'is', 'a', 'test', _id='123', _class='myclass')]]
ele é processado como:
<div id="123" class="myclass">thisisatest</div>
`` Div`` é uma classe auxiliar, ou seja, algo que pode ser usado para construir HTML programaticamente. Corresponde ao HTML `` <div> tag ``.
Argumentos posicionais são interpretados como objetos contidos entre as tags de abrir e fechar. argumentos nomeados que começam com um sublinhado são interpretados como atributos de tags HTML (sem o sublinhado). Alguns helpers também têm argumentos nomeados que não começam com sublinhado; estes argumentos são específicos do tag.
Em vez de um conjunto de argumentos sem nome, um helper também pode ter uma única lista ou tupla como seu conjunto de componentes usando a notação `` * `` e pode levar um único dicionário como seu conjunto de atributos usando o `` ** ` `, por exemplo:
[[
contents = ['this', 'is', 'a', 'test']
attributes = {'_id':'123', '_class':'myclass'}
=DIV(*contents, **attributes)
]]
(Produz a mesma saída que antes).
O seguinte conjunto de helpers:
A
, BEAUTIFY
, BODY
, CAT
, CODE
, DIV
, EM
,
FORM
, H1
, H2
, H3
, H4
, H5
, H6
, HEAD
,
HTML
, IMG
, INPUT
, LABEL
, LI
, METATAG
,
OL
, OPTION
, P
, PRE
, SELECT
, SPAN
, STRONG
,
TABLE
, TAG
, TAGGER
, THEAD
, TBODY
, TD
,
TEXTAREA
, TH
, TT
, TR
, UL
, XML
, xmlescape
,
I
, META
, LINK
, TITLE
, STYLE
, SCRIPT
pode ser usado para construir expressões complexas que podem então ser serializado para XML. Por exemplo:
[[=DIV(STRONG(I("hello ", "<world>")), _class="myclass")]]
é prestado:
<div class="myclass"><strong><i>hello <world></i></strong></div>
Ajudantes também podem ser serializados em cordas, de forma equivalente, com a `` __str__`` e os `` métodos xml``:
>>> str(DIV("hello world"))
'<div>hello world</div>'
>>> DIV("hello world").xml()
'<div>hello world</div>'
The helpers mechanism in py4web is more than a system to generate HTML without concatenating strings. It provides a server-side representation of the document object model (DOM).
Componentes de helpers podem ser referenciados através de sua posição, e helpers agir como listas com relação aos seus componentes:
>>> a = DIV(SPAN('a', 'b'), 'c')
>>> print(a)
<div><span>ab</span>c</div>
>>> del a[1]
>>> a.append(STRONG('x'))
>>> a[0][0] = 'y'
>>> print(a)
<div><span>yb</span><strong>x</strong></div>
Atributos de helpers pode ser referenciado pelo nome, e helpers agir como dicionários com relação aos seus atributos:
>>> a = DIV(SPAN('a', 'b'), 'c')
>>> a['_class'] = 's'
>>> a[0]['_class'] = 't'
>>> print(a)
<div class="s"><span class="t">ab</span>c</div>
Note, the complete set of components can be accessed via a list called
a.children
, and the complete set of attributes can be accessed via
a dictionary called a.attributes
. So, a[i]
is equivalent to
a.children[i]
when i
is an integer, and a[s]
is equivalent
to a.attributes[s]
when s
is a string.
Note que atributos auxiliares são passados como argumentos para o auxiliar. Em alguns casos, no entanto, nomes de atributos incluem caracteres especiais que não são permitidos em identificadores Python (por exemplo, hífens) e, portanto, não podem ser usados como nomes de argumentos de palavra-chave. Por exemplo:
DIV('text', _data-role='collapsible')
will not work because “_data-role” includes a hyphen, which will produce a Python syntax error.
In such cases you can pass the attributes as a dictionary and make use
of Python’s **
function arguments notation, which maps a dictionary
of (key:value) pairs into a set of keyword arguments:
>>> print(DIV('text', **{'_data-role': 'collapsible'}))
<div data-role="collapsible">text</div>
Você também pode criar dinamicamente tags especiais:
>>> print(TAG['soap:Body']('whatever', **{'_xmlns:m':'http://www.example.org'}))
<soap:Body xmlns:m="http://www.example.org">whatever</soap:Body>
`` XML``¶
`` XML`` é um objeto usado para encapsular texto que não deve ser escapado. O texto pode ou não conter XML válido. Por exemplo, poderia conter JavaScript.
O texto neste exemplo é escapado:
>>> print(DIV("<strong>hello</strong>"))
<div><strong>hello</strong></div>
usando `` XML`` você pode impedir escapar:
>>> print(DIV(XML("<strong>hello</strong>")))
<div><strong>hello</strong></div>
Às vezes você quer renderizar HTML armazenado em uma variável, mas o HTML pode conter tags inseguras como scripts:
>>> print(XML('<script>alert("unsafe!")</script>'))
<script>alert("unsafe!")</script>
Un-escaped executable input such as this (for example, entered in the body of a comment in a blog) is unsafe, because it can be used to generate cross site scripting (XSS) attacks against other visitors to the page.
O py4web `` helper XML`` pode higienizar nosso texto para evitar injeções e escapar todas as tags exceto aqueles que você permitir explicitamente. Aqui está um exemplo:
>>> print(XML('<script>alert("unsafe!")</script>', sanitize=True))
<script>alert("unsafe!")</script>
Os `` construtores XML``, por padrão, considere o conteúdo de algumas tags e alguns de seus atributos de segurança. Você pode substituir os padrões usando os opcionais `` permitted_tags`` e `` allowed_attributes`` argumentos. Aqui estão os valores padrão dos argumentos opcionais do `` helper XML``.
XML(text, sanitize=False,
permitted_tags=['a', 'b', 'blockquote', 'br/', 'i', 'li',
'ol', 'ul', 'p', 'cite', 'code', 'pre', 'img/',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'table', 'tr', 'td',
'div', 'strong', 'span'],
allowed_attributes={'a': ['href', 'title', 'target'],
'img': ['src', 'alt'], 'blockquote': ['type'], 'td': ['colspan']})
Built-in helpers¶
`` A``¶
Este assistente é usado para construir ligações.
>>> print(A('<click>', XML('<strong>me</strong>'),
_href='http://www.py4web.com'))
<a href="http://www.py4web.com"><click><strong>me</strong></a>
`` BODY``¶
Este assistente faz com que o corpo de uma página.
>>> print(BODY('<hello>', XML('<strong>world</strong>'), _bgcolor='red'))
<body bgcolor="red"><hello><strong>world</strong></body>
`` CAT``¶
This helper concatenates other helpers.
>>> print(CAT('Here is a ', A('link', _href='target'), ', and here is some ', STRONG('bold text'), '.'))
Here is a <a href="target">link</a>, and here is some <strong>bold text</strong>.
`` Div``¶
This is the content division element.
>>> print(DIV('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<div id="0" class="test"><hello><strong>world</strong></div>
`` EM``¶
Insiste no seu conteúdo.
>>> print(EM('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<em id="0" class="test"><hello><strong>world</strong></em>
`` Form``¶
Use this helper to make a FORM for user input. Forms will be discussed in detail in Chapter 12.
>>> print(FORM(INPUT(_type='submit'), _action='', _method='post'))
<form action="" method="post"><input type="submit"/></form>
`` H1``, `` h2``, `` H3``, `` H4``, `` H5``, `` H6``¶
These helpers are for paragraph headings and subheadings.
>>> print(H1('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<h1 id="0" class="test"><hello><strong>world</strong></h1>
`` HEAD``¶
Para marcar a cabeça de uma página HTML.
>>> print(HEAD(TITLE('<hello>', XML('<strong>world</strong>'))))
<head><title><hello><strong>world</strong></title></head>
`` HTML``¶
For tagging an HTML page.
>>> print(HTML(BODY('<hello>', XML('<strong>world</strong>'))))
<html><body><hello><strong>world</strong></body></html>
`` I``¶
Este assistente torna o seu conteúdo em itálico.
>>> print(I('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<i id="0" class="test"><hello><strong>world</strong></i>
`` IMG``¶
It can be used to embed images into HTML.
>>> print(IMG(_src='http://example.com/image.png', _alt='test'))
<img alt="test" src="http://example.com/image.png"/>
Aqui é uma combinação de helpers A, IMG, e URL para a inclusão de uma imagem estática com um link:
>>> print(A(IMG(_src=URL('static', 'logo.png'), _alt="My Logo"),
... _href=URL('default', 'index')))
<a href="/default/index"><img alt="My Logo" src="/static/logo.png"/></a>
`` INPUT``¶
Cria um `` <input … /> `` tag. Uma tag de entrada não pode conter outras tags, e é fechada por `` /> `` em vez de > ``. A tag de entrada tem um atributo opcional `` _type
que pode ser definido como “texto” (o padrão), “enviar”, “caixa”, ou “rádio”.
>>> print(INPUT(_name='test', _value='a'))
<input name="test" value="a"/>
For radio buttons use the _checked
attribute:
>>> for v in ['a', 'b', 'c']:
... print(INPUT(_type='radio', _name='test', _value=v, _checked=v=='b'), v)
...
<input name="test" type="radio" value="a"/> a
<input checked="checked" name="test" type="radio" value="b"/> b
<input name="test" type="radio" value="c"/> c
e similarmente para caixas de seleção:
>>> print(INPUT(_type='checkbox', _name='test', _value='a', _checked=True))
<input checked="checked" name="test" type="checkbox" value="a"/>
>>> print(INPUT(_type='checkbox', _name='test', _value='a', _checked=False))
<input name="test" type="checkbox" value="a"/>
`` Label``¶
Ele é usado para criar uma tag rótulo para um campo de entrada.
>>> print(LABEL('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<label id="0" class="test"><hello><strong>world</strong></label>
`` LI``¶
Faz um item da lista e deve estar contido em um `` UL`` ou `` tag OL``.
>>> print(LI('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<li id="0" class="test"><hello><strong>world</strong></li>
`` OL``¶
It stands for ordered list. The list should contain LI tags.
>>> print(OL(LI('<hello>'), LI(XML('<strong>world</strong>')), _class='test', _id=0))
<ol class="test" id="0"><li><hello></li><li><strong>world</strong></li></ol>
`` OPTION``¶
This should only be used as argument of a SELECT
.
>>> print(OPTION('<hello>', XML('<strong>world</strong>'), _value='a'))
<option value="a"><hello><strong>world</strong></option>
For selected options use the _selected
attribute:
>>> print(OPTION('Thank You', _value='ok', _selected=True))
<option selected="selected" value="ok">Thank You</option>
`` P``¶
Isto é para marcar um parágrafo.
>>> print(P('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<p id="0" class="test"><hello><strong>world</strong></p>
`` PRE``¶
Gera um `` <pre> … </ pre> `` tag para exibir texto pré-formatado. O `` CODE`` auxiliar é geralmente preferível para listagens de código.
>>> print(SELECT(OPTION('first', _value='1'), OPTION('second', _value='2'), _class='test', _id=0))
<pre id="0" class="test"><hello><strong>world</strong></pre>
`` SCRIPT``¶
This is for include or link a script, such as JavaScript.
>>> print(SCRIPT('console.log("hello world");', _type='text/javascript'))
<script type="text/javascript">console.log("hello world");</script>
`` SELECT``¶
Makes a <select>...</select>
tag. This is used with the OPTION
helper.
>>> print(SELECT(OPTION('first', _value='1'), OPTION('second', _value='2'),
... _class='test', _id=0))
<select class="test" id="0"><option value="1">first</option><option value="2">second</option></select>
`` SPAN``¶
Semelhante a `` div`` mas utilizado para marcação em linha (em vez de bloco) conteúdo.
>>> print(SPAN('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<span id="0" class="test"><hello><strong>world</strong></span>
`` STYLE``¶
Semelhante ao script, mas usadas para incluir ou código do link CSS. Aqui, o CSS está incluído:
>>> print(STYLE(XML('body {color: white}')))
<style>body {color: white}</style>
e aqui ela está ligada:
>>> print(STYLE(_src='style.css'))
<style src="style.css"></style>
`` TABLE``, `` TR``, `` TD``¶
Estas tags (juntamente com o opcional `` THEAD`` e `` helpers TBODY``) são utilizados para tabelas de construção HTML.
>>> print(TABLE(TR(TD('a'), TD('b')), TR(TD('c'), TD('d'))))
<table><tr><td>a</td><td>b</td></tr><tr><td>c</td><td>d</td></tr></table>
TR
expects TD
content.
É fácil converter uma matriz de Python em uma tabela HTML usando `` * `` notação argumentos de função do Python, que mapeia os elementos da lista para os argumentos da função posicionais.
Aqui, vamos fazê-lo linha por linha:
>>> table = [['a', 'b'], ['c', 'd']]
>>> print(TABLE(TR(*map(TD, table[0])), TR(*map(TD, table[1]))))
<table><tr><td>a</td><td>b</td></tr><tr><td>c</td><td>d</td></tr></table>
Aqui nós fazer todas as linhas de uma só vez:
>>> table = [['a', 'b'], ['c', 'd']]
>>> print(TABLE(*[TR(*map(TD, rows)) for rows in table]))
<table><tr><td>a</td><td>b</td></tr><tr><td>c</td><td>d</td></tr></table>
`` TBODY``¶
Isto é usado para linhas tag contidos no corpo de mesa, em oposição a linhas de cabeçalho ou de rodapé. É opcional.
>>> print(TBODY(TR(TD('<hello>')), _class='test', _id=0))
<tbody id="0" class="test"><tr><td><hello></td></tr></tbody>
`` TEXTAREA``¶
Este assistente faz uma <textarea> … </ textarea> tag ``.
>>> print(TEXTAREA('<hello>', XML('<strong>world</strong>'), _class='test',
... _cols="40", _rows="10"))
<textarea class="test" cols="40" rows="10"><hello><strong>world</strong></textarea>
`` TH``¶
Este é utilizado em vez de `` TD`` em cabeçalhos de tabela.
>>> print(TH('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<th id="0" class="test"><hello><strong>world</strong></th>
`` THEAD``¶
Isto é usado para linhas de cabeçalho da tabela tag.
>>> print(THEAD(TR(TH('<hello>')), _class='test', _id=0))
<thead id="0" class="test"><tr><th><hello></th></tr></thead>
`` TITLE``¶
Isto é usado para marcar o título de uma página em um cabeçalho HTML.
>>> print(TITLE('<hello>', XML('<strong>world</strong>')))
<title><hello><strong>world</strong></title>
`` TT``¶
Etiquetas de texto como máquina de escrever texto (monoespaçada).
>>> print(TT('<hello>', XML('<strong>world</strong>'), _class='test', _id=0))
<tt id="0" class="test"><hello><strong>world</strong></tt>
`` UL``¶
It stands for unordered list. The list should contain LI tags.
>>> print(UL(LI('<hello>'), LI(XML('<strong>world</strong>')), _class='test', _id=0))
<ul class="test" id="0"><li><hello></li><li><strong>world</strong></li></ul>
`` URL``¶
The URL helper is not part of yatl package, instead it is provided by py4web.
Helpers personalizados¶
`` TAG``¶
Às vezes você precisa para gerar tags XML personalizados. py4web fornece `` TAG``, um gerador de tag universal.
[[=TAG.name('a', 'b', _c='d')]]
gera o seguinte XML:
<name c="d">ab</name>
Argumentos “a”, “b” e “d” são automaticamente escapou; usar o `` helper XML`` para suprimir esse comportamento. Usando `` TAG`` você pode gerar HTML / XML marcas já não fornecidos pela API. As etiquetas podem ser aninhados, e são serializados com `` str () `` Uma sintaxe é equivalente.:
[[=TAG['name']('a', 'b', _c='d')]]
Tags com auto-fechamento podem ser geradas com o helper TAG. O noma da tag deve terminar com um “/”.
[[=TAG['link/'](_href='http://py4web.com')]]
gera o seguinte XML:
<link ref="http://py4web.com"/>
Notice that TAG
is an object, and TAG.name
or TAG['name']
is
a function that returns an helper instance.
`` BEAUTIFY``¶
`` BEAUTIFY`` é usado para representações de construção HTML de objetos compostos, incluindo listas, tuplas e dicionários:
[[=BEAUTIFY({"a": ["hello", STRONG("world")], "b": (1, 2)})]]
`` BEAUTIFY`` retorna um objeto serializado XML-like to XML, com uma representação de vista agradável de seu argumento construtor. Neste caso, a representação XML:
{"a": ["hello", STRONG("world")], "b": (1, 2)}
retribuirá como:
<table><tbody>
<tr><th>a</th><td><ul><li>hello</li><li><strong>world</strong></li></ul></td></tr>
<tr><th>b</th><td>(1, 2)</td></tr>
</tbody></table>
Server-side DOM¶
children
¶
Each helper object keep the list of its components into the children
attribute.
>>> CAT('hello', STRONG('world')).children
['hello', <yatl.helpers.TAGGER object at 0x7fa533ff7640>]
find
¶
To help searching into the DOM, all helpers have a find
method with
the following signature:
def find(self, query=None, **kargs)
that returns all the components matching supplied arguments.
A very simple query
can be a tag name:
>>> a = DIV(DIV(SPAN('x'), 3, DIV(SPAN('y'))))
>>> for c in a.find('span', first_only=True): c[0]='z'
>>> print(a) # We should .xml() here instead of print
<div><div><span>z</span>3<div><span>y</span></div></div></div>
>>> for c in a.find('span'): c[0]='z'
>>> print(a)
<div><div><span>z</span>3<div><span>z</span></div></div></div>
It also supports a syntax compatible with jQuery, accepting the following expressions:
jQuery Multiple Selector, e.g. “selector1, selector2, selectorN”,
jQuery Descendant Selector, e.g. “ancestor descendant”,
jQuery ID Selector, e.g. “#id”,
jQuery Class Selector, e.g. “.class”, and
jQuery Attribute Equals Selector, e.g. “[name=value]”, notice that here the value must be unquoted.
Here are some examples:
>>> a = DIV(SPAN(A('hello', **{'_id': '1-1', '_u:v': '$'})), P('world', _class='this is a test'))
>>> for e in a.find('div a#1-1, p.is'): print(e)
<a id="1-1" u:v="$">hello</a>
<p class="this is a test">world</p>
>>> for e in a.find('#1-1'): print(e)
<a id="1-1" u:v="$">hello</a>
>>> a.find('a[u:v=$]')[0].xml()
'<a id="1-1" u:v="$">hello</a>'
>>> a = FORM(INPUT(_type='text'), SELECT(OPTION(0)), TEXTAREA())
>>> for c in a.find('input, select, textarea'): c['_disabled'] = True
>>> a.xml()
'<form><input disabled="disabled" type="text"/><select disabled="disabled"><option>0</option></select><textarea disabled="disabled"></textarea></form>'
>>> for c in a.find('input, select, textarea'): c['_disabled'] = False
>>> a.xml()
'<form><input type="text"/><select><option>0</option></select><textarea></textarea></form>'
Elements that are matched can also be replaced or removed by specifying
a replace
argument (note, a list of the original matching elements
is still returned as usual).
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y', _class='abc'), SPAN('z', _class='abc'))))
>>> b = a.find('span.abc', replace=P('x', _class='xyz'))
>>> print(a)
<div><div><p class="xyz">x</p><div><p class="xyz">x</p><p class="xyz">x</p></div></div></div>
replace
can be a callable, which will be passed the original element and
should return a new element to replace it.
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y', _class='abc'), SPAN('z', _class='abc'))))
>>> b = a.find('span.abc', replace=lambda el: P(el[0], _class='xyz'))
>>> print(a)
<div><div><p class="xyz">x</p><div><p class="xyz">y</p><p class="xyz">z</p></div></div></div>
Se `` substituir = None``, os elementos correspondentes serão completamente removidas.
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y', _class='abc'), SPAN('z', _class='abc'))))
>>> b = a.find('span', text='y', replace=None)
>>> print(a)
<div><div><span class="abc">x</span><div><span class="abc"></span><span class="abc">z</span></div></div></div>
If a text
argument is specified, elements will be searched for text
components that match text, and any matching text components will be
replaced (text
is ignored if replace
is not also specified, use
a find
argument when you only need searching for textual elements).
Like the find
argument, text
can be a string or a compiled regex.
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y', _class='abc'), SPAN('z', _class='abc'))))
>>> b = a.find(text=re.compile('x|y|z'), replace='hello')
>>> print(a)
<div><div><span class="abc">hello</span><div><span class="abc">hello</span><span class="abc">hello</span></div></div></div>
If other attributes are specified along with text
, then only components
that match the specified attributes will be searched for text.
>>> a = DIV(DIV(SPAN('x', _class='abc'), DIV(SPAN('y', _class='efg'), SPAN('z', _class='abc'))))
>>> b = a.find('span.efg', text=re.compile('x|y|z'), replace='hello')
>>> print(a)
<div><div><span class="abc">x</span><div><span class="efg">hello</span><span class="abc">z</span></div></div></div>
Layout da página¶
Visualizações pode estender e incluir outros pontos de vista em uma estrutura de árvore.
Por exemplo, podemos pensar em uma visão “index.html” que se estende “layout.html” e inclui “body.html”. Ao mesmo tempo, “layout.html” pode incluir “header.html” e “footer.html”.
A raiz da árvore é o que chamamos de exibição de layout. Assim como qualquer outro arquivo de modelo HTML, você pode editá-lo usando a interface administrativa py4web. O nome do arquivo “layout.html” é apenas uma convenção.
Aqui está uma página minimalista que se estende a visão “layout.html” e inclui o ponto de vista “page.html”:
[[extend 'layout.html']]
<h1>Hello World</h1>
[[include 'page.html']]
O arquivo de layout estendido deve conter um `` [[incluir]] `` directiva, algo como:
<html>
<head>
<title>Page Title</title>
</head>
<body>
[[include]]
</body>
</html>
Quando o ponto de vista é chamado, o (layout) vista alargada é carregado, e o ponto de vista chamando substitui a `` [[incluir]] `` directiva dentro da disposição. O processamento continua de forma recursiva até que todo `` `` extend`` e directivas include`` tenham sido processados. O modelo resultante é então traduzido em código Python. Note, quando um aplicativo é bytecode compilado, é este código Python que é compilado, não a visão original próprios arquivos. Assim, a versão bytecode compilado de um determinado ponto de vista é um único arquivo .pyc que inclui o código Python não apenas para o arquivo de exibição original, mas para toda a sua árvore de pontos de vista estendidas e incluídos.
`` Extend``, `` include``, `` block`` e `` super`` são directivas especiais do template, e não comandos Python.
Qualquer conteúdo ou código que precede a `` [[estender …]] `` directiva será inserido (e, portanto, executado) antes do início do conteúdo / código da vista estendida. Embora este não é normalmente usado para inserir conteúdo HTML real antes de o conteúdo da exibição estendida, ele pode ser útil como um meio para definir variáveis ou funções que você deseja disponibilizar para a exibição estendida. Por exemplo, considere uma visão “index.html”:
[[sidebar_enabled=True]]
[[extend 'layout.html']]
<h1>Home Page</h1>
e um trecho de “layout.html”:
[[if sidebar_enabled:]]
<div id="sidebar">
Sidebar Content
</div>
[[pass]]
Porque o `` atribuição sidebar_enabled`` em “index.html” vem antes do `` extend``, essa linha é inserido antes do início do “layout.html”, fazendo com que `` qualquer lugar sidebar_enabled`` disponível dentro do “layout. html”código (uma versão um pouco mais sofisticada deste é usado no bem-vindo ** ** app).
Também é importante ressaltar que as variáveis retornadas pela função de controlador estão disponíveis não só na vista principal da função, mas em todos os seus pontos de vista estendidas e incluídos também.
O argumento de um `` `` extend`` ou include`` (isto é, o nome vista alargada ou incluído) possa ser uma variável Python (embora não uma expressão Python). No entanto, este impõe uma limitação - vistas que usar variáveis no `` extend`` ou `` declarações include`` não pode ser bytecode compilado. Como mencionado acima, vista compilado-bytecode incluem toda a árvore de pontos de vista estendidas e incluídos, de modo que o específica estendida e vistas incluídos deve ser conhecido em tempo de compilação, que não é possível se os nomes de exibição são variáveis (cujos valores não são determinados até run Tempo). Porque vistas bytecode compilação pode fornecer um impulso de velocidade significativa, utilizando variáveis em `` extend`` e `` include`` geralmente deve ser evitada, se possível.
Em alguns casos, uma alternativa para usar uma variável em um `` include`` é simplesmente para colocar regulares `` [[incluem …]] `` directivas dentro de um `` se … bloco else``.
[[if some_condition:]]
[[include 'this_view.html']]
[[else:]]
[[include 'that_view.html']]
[[pass]]
O código acima não apresenta qualquer problema para a compilação bytecode porque há variáveis estão envolvidas. Note, no entanto, que o bytecode compilado vista realmente irá incluir o código Python para ambos “this_view.html” e “that_view.html”, embora apenas o código para um desses pontos de vista serão executadas, dependendo do valor de `` some_condition ``.
Tenha em mente, isso só funciona para `` include`` - você não pode colocar `` [[estender …]] `` directivas dentro `` se … blocos else``.
Layouts são usados para página encapsular comunalidade (cabeçalhos, rodapés, menus), e embora eles não são obrigatórios, eles vão fazer a sua aplicação mais fácil de escrever e manter. Em particular, sugerimos escrever layouts que aproveitam as seguintes variáveis que podem ser definidas no controlador. Usando estas variáveis bem conhecidas irá ajudar a tornar seus layouts intercambiáveis:
response.title
response.subtitle
response.meta.author
response.meta.keywords
response.meta.description
response.flash
response.menu
response.files
Exceto para `` menu`` e `` files``, estas são todas as cordas e seu significado deve ser óbvia.
`` Menu response.menu`` está uma lista de 3-tuplas ou 4-tuplas. Os três elementos são: o nome do link, um booleano representando se o link está ativo (é o elo atual), e o URL da página vinculada. Por exemplo:
response.menu = [('Google', False, 'http://www.google.com', []),
('Index', True, URL('index'), [])]
O quarto elemento tupla é um sub-menu de opcionais.
`` Response.files`` é uma lista de arquivos CSS e JS que são necessários pelo sua página.
Também recomendamos que você usa:
[[include 'py4web_ajax.html']]
na cabeça HTML, uma vez que irá incluir as bibliotecas jQuery e definir algumas funções JavaScript compatível com versões anteriores para efeitos especiais e Ajax. “Py4web_ajax.html” inclui os `` tag response.meta`` na vista, base jQuery, o datepicker calendário, e todos CSS necessário e JS `` response.files``.
Layout de página padrão¶
O “views / layout.html” que acompanha o aplicativo andaimes py4web ** boas-vindas ** (despojado de algumas partes opcionais) é bastante complexa, mas tem a seguinte estrutura:
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>[[=response.title or request.application]]</title>
...
<script src="[[=URL('static', 'js/modernizr.custom.js')]]"></script>
[[
response.files.append(URL('static', 'css/py4web.css'))
response.files.append(URL('static', 'css/bootstrap.min.css'))
response.files.append(URL('static', 'css/bootstrap-responsive.min.css'))
response.files.append(URL('static', 'css/py4web_bootstrap.css'))
]]
[[include 'py4web_ajax.html']]
[[
# using sidebars need to know what sidebar you want to use
left_sidebar_enabled = globals().get('left_sidebar_enabled', False)
right_sidebar_enabled = globals().get('right_sidebar_enabled', False)
middle_columns = {0:'span12', 1:'span9', 2:'span6'}[
(left_sidebar_enabled and 1 or 0)+(right_sidebar_enabled and 1 or 0)]
]]
[[block head]][[end]]
</head>
<body>
<!-- Navbar ================================================== -->
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="flash">[[=response.flash or '']]</div>
<div class="navbar-inner">
<div class="container">
[[=response.logo or '']]
<ul id="navbar" class="nav pull-right">
[[='auth' in globals() and auth.navbar(mode="dropdown") or '']]
</ul>
<div class="nav-collapse">
[[if response.menu:]]
[[=MENU(response.menu)]]
[[pass]]
</div><!--/.nav-collapse -->
</div>
</div>
</div><!--/top navbar -->
<div class="container">
<!-- Masthead ================================================== -->
<header class="mastheader row" id="header">
<div class="span12">
<div class="page-header">
<h1>
[[=response.title or request.application]]
<small>[[=response.subtitle or '']]</small>
</h1>
</div>
</div>
</header>
<section id="main" class="main row">
[[if left_sidebar_enabled:]]
<div class="span3 left-sidebar">
[[block left_sidebar]]
<h3>Left Sidebar</h3>
<p></p>
[[end]]
</div>
[[pass]]
<div class="[[=middle_columns]]">
[[block center]]
[[include]]
[[end]]
</div>
[[if right_sidebar_enabled:]]
<div class="span3">
[[block right_sidebar]]
<h3>Right Sidebar</h3>
<p></p>
[[end]]
</div>
[[pass]]
</section><!--/main-->
<!-- Footer ================================================== -->
<div class="row">
<footer class="footer span12" id="footer">
<div class="footer-content">
[[block footer]] <!-- this is default footer -->
...
[[end]]
</div>
</footer>
</div>
</div> <!-- /container -->
<!-- The javascript =============================================
(Placed at the end of the document so the pages load faster) -->
<script src="[[=URL('static', 'js/bootstrap.min.js')]]"></script>
<script src="[[=URL('static', 'js/py4web_bootstrap.js')]]"></script>
[[if response.google_analytics_id:]]
<script src="[[=URL('static', 'js/analytics.js')]]"></script>
<script type="text/javascript">
analytics.initialize({
'Google Analytics':{trackingId:'[[=response.google_analytics_id]]'}
});</script>
[[pass]]
</body>
</html>
Existem algumas características deste layout padrão que tornam muito fácil de usar e personalizar:
Ele é escrito em HTML5 e usa a biblioteca “Modernizr” para compatibilidade com versões anteriores. O layout real inclui algumas declarações condicionais extras exigidos pelo IE e eles são omitidos por brevidade.
Ele exibe tanto `` response.title`` e `` response.subtitle`` que pode ser definido em um modelo ou um controlador. Se eles não estão definidos, adota o nome do aplicativo como título.
Ele inclui o arquivo `` py4web_ajax.html`` no cabeçalho que gerou todas as declarações de importação da ligação e de script.
Ele usa uma versão modificada do Twitter Bootstrap para layouts flexíveis que funciona em dispositivos móveis e colunas reorganiza para caber telas pequenas.
Ele usa “analytics.js” para se conectar ao Google Analytics.
O `` [[= auth.navbar (…)]] `` exibe uma recepção para o usuário atual e links para as funções de autenticação, como login, logout, registro, alteração de senha, etc. dependendo do contexto. `` Auth.navbar`` é uma fábrica auxiliar e a sua saída podem ser manipulados como qualquer outro auxiliar. É colocado em uma expressão para verificar a existência de auth definição, as avalia a expressão ‘’ no caso de auth é indefinido.
O `` [[= MENU (response.menu)]] `` exibe a estrutura do menu como `` <ul> … </ ul> ``.
`` [[Incluir]] `` é substituído pelo conteúdo da vista que se prolonga, quando a página é processada.
Por padrão, ele usa uma de três colunas condicional (a esquerda e barras laterais direitas pode ser desligado com as vistas que se estendem)
Ele usa as seguintes classes: page-header, principal, rodapé.
Ele contém os seguintes blocos: cabeça, left_sidebar, centro, right_sidebar, rodapé.
Em vista, você pode ativar e personalizar barras laterais da seguinte forma:
[[left_sidebar_enabled=True]]
[[extend 'layout.html']]
This text goes in center
[[block left_sidebar]]
This text goes in sidebar
[[end]]
Personalizando o layout padrão¶
Personalizando o layout padrão sem edição é fácil, porque a aplicação de boas-vindas é baseado no Twitter Bootstrap que está bem documentado e suporta temas. Em py4web quatro arquivos estáticos que são relevantes para o estilo:
“Css / py4web.css” contém estilos py4web específicos
“Css / bootstrap.min.css” contém o estilo CSS Twitter Bootstrap
“Css / py4web_bootstrap.css”, que substitui alguns estilos Bootstrap para se conformar às necessidades py4web.
“js / bootstrap.min.js”, que inclui as bibliotecas para efeitos de menu, modais, painéis.
Para alterar as cores e imagens de fundo, tente anexar o seguinte código ao header layout.html:
<style>
body { background: url('images/background.png') repeat-x #3A3A3A; }
a { color: #349C01; }
.page-header h1 { color: #349C01; }
.page-header h2 { color: white; font-style: italic; font-size: 14px;}
.statusbar { background: #333333; border-bottom: 5px #349C01 solid; }
.statusbar a { color: white; }
.footer { border-top: 5px #349C01 solid; }
</style>
Claro que você também pode substituir completamente o “layout.html” e arquivos “py4web.css” com o seu próprio.
Desenvolvimento móvel¶
Embora o layout.html padrão é projetado para ser compatível com telemóvel, pode-se às vezes é preciso usar diferentes pontos de vista quando uma página é visitada por um dispositivo móvel.
Para tornar a desenvolver para desktop e dispositivos móveis mais fáceis, py4web inclui o `` @ mobilize`` decorador. Este decorador é aplicado a ações que devem ter uma visão normal e uma exibição móvel. Isso é demonstrado aqui:
from gluon.contrib.user_agent_parser import mobilize
@mobilize
def index():
return dict()
Observe que o decorador deve ser importada antes de usá-lo em um controlador. Quando a função “index” é chamado a partir de um browser normal (computador de mesa), py4web tornará o dicionário retornado usando a exibição “[controller] /index.html”. No entanto, quando ele é chamado por um dispositivo móvel, o dicionário vai ser processado por “[controller] /index.mobile.html”. Observe que visualizações móveis têm a extensão “mobile.html”.
Alternativamente, você pode aplicar a seguinte lógica para fazer todos os pontos de vista móvel amigável:
if request.user_agent().is_mobile:
response.view.replace('.html', '.mobile.html')
The task of creating the “*.mobile.html” views is left to the developer but we strongly suggest using the “jQuery Mobile” plugin which makes the task very easy.
Funções em vista¶
Considere isso “layout.html”:
<html>
<body>
[[include]]
<div class="sidebar">
[[if 'mysidebar' in globals():]][[mysidebar()]][[else:]]
my default sidebar
[[pass]]
</div>
</body>
</html>
e este ponto de vista que se prolonga
[[def mysidebar():]]
my new sidebar!!!
[[return]]
[[extend 'layout.html']]
Hello World!!!
Repare que a função é definida antes do `` [[estender …]] `` declaração - Isto resulta na função que está sendo criado antes do código “layout.html” é executado, assim que a função pode ser chamado em qualquer lugar dentro “layout. html”, mesmo antes do` [[incluir]] . Observe também a função está incluída na vista alargada sem a ` = `` prefixo.
O código gera o seguinte resultado:
<html>
<body>
Hello World!!!
<div class="sidebar">
my new sidebar!!!
</div>
</body>
</html>
Observe que a função é definida em HTML (embora ele também poderia conter código Python) para que `` response.write`` é usado para gravar o seu conteúdo (a função não retornar o conteúdo). É por isso que o layout chama a função de visão utilizando `` [[mysidebar ()]] `` `` em vez de [[= mysidebar ()]] ``. Funções definidas desta forma pode ter argumentos.
Blocos em vista¶
O caminho principal para fazer uma vista mais modular é usando `` [[bloco …]] `` s e este mecanismo é uma alternativa para o mecanismo discutido na secção anterior.
Para entender como isso funciona, considere aplicativos baseado no bem-vindo andaimes aplicativo, que tem um layout.html vista. Este ponto de vista é estendida pela vista `` padrão / index.html`` via `` [[estender “layout.html”]] ``. O conteúdo do layout.html predefinir certos blocos com determinado conteúdo padrão, e estes são, portanto, incluídos em default / index.html.
Você pode substituir esses blocos de conteúdo padrão, colocando o seu novo conteúdo dentro do mesmo nome do bloco. A localização do bloco no layout.html não é alterado, mas o conteúdo é.
Aqui está uma versão Simplificado. Imagine isto é “layout.html”:
<html>
<body>
[[include]]
<div class="sidebar">
[[block mysidebar]]
my default sidebar (this content to be replaced)
[[end]]
</div>
</body>
</html>
e isto é um simples que se estende vista `` padrão / index.html``:
[[extend 'layout.html']]
Hello World!!!
[[block mysidebar]]
my new sidebar!!!
[[end]]
Ele gera a saída seguinte, quando o teor é fornecido pelo bloco sobre-montada na vista estendendo-se, ainda a DIV envolvente e classe vem de layout.html. Isso permite que a consistência entre os pontos de vista:
<html>
<body>
Hello World!!!
<div class="sidebar">
my new sidebar!!!
</div>
</body>
</html>
O verdadeiro layout.html define um número de blocos úteis, e você pode facilmente adicionar mais para coincidir com o layout seu desejo.
Você pode ter muitos blocos, e se um bloco está presente na exibição estendida, mas não na visão estendendo, o conteúdo da visão ampliada é usado. Além disso, observe que, ao contrário com as funções, não é necessário definir blocos antes do `` [[estender …]] `` - mesmo se definido após o `` extend``, eles podem ser usados para fazer substituições em qualquer lugar a vista estendida.
Dentro de um bloco, você pode usar a expressão `` [[Super]] `` para incluir o conteúdo do pai. Por exemplo, se substituir o acima estendendo vista com:
[[extend 'layout.html']]
Hello World!!!
[[block mysidebar]]
[[super]]
my new sidebar!!!
[[end]]
nós temos:
<html>
<body>
Hello World!!!
<div class="sidebar">
my default sidebar
my new sidebar!
</div>
</body>
</html>