Version 4 (modified by apoirier, 11 years ago) (diff) |
---|
The Renderer objects
Creating a renderer
As described in ComponentModel, the views of a component received a renderer. A renderer is a DOM objects factory that the developer uses to build the DOM tree of the view (see PresentationTier):
from nagare import presentation class App: pass @presentation.render_for(App): def render(self, h, *args): # the `h` parameter is the renderer, used to generate a DOM tree return h.div(h.h1('Hello world !'))
By default, each views receive a new XHTML renderer (instance of the Renderer class of namespaces/xhtml.py#xhtml.Renderer) suitable to build a synchronous (X)HTML DOM tree.
A view can also create a different renderer, for example to generate an other XML dialect than XHTML:
from nagare import presentation from nagare.namespaces import xml class App: pass @presentation.render_for(App): def render(self, h, *args): h.response.content_type = 'text/xml' x = xml.Renderer(h) # Creating a XML renderer return x.contact(x.name('John Doe'), x.age(20))
or to generate an asynchronous view of a component:
from nagare import presentation, component from nagare.namespaces import xhtml from MyBlog import Blog class App: def __init__(self): self.content = component.Component(Blog()) @presentation.render_for(App): def render(self, h, *args): # Creating an asynchronous XHTML renderer a = xhtml.AsyncRenderer(h) return h.div(self.content.render(a))
Note
The new renderer must be created with the current renderer as first parameter, to maintain a parent/child relationship between them.
Default renderers
XHTML renderer
A XHTML renderer is an instance of the Renderer class of namespaces/xhtml.py#xhtml.Renderer.
A XHTML renderer is a factory for all the possible XHTML tags. It also has:
- a request and a response attributes which are WebOb Request and Response objects.
- a head attribute which is a Head renderer instance, see below.
- the following methods:
- parse_html(self, source, fragment=False, no_leading_text=False, xhtml=False) -- to read HTML or XHTML (choosen with the xhtml parameter) from the source file to a DOM tree. If fragment is True, the (X)HTML read can have multiple roots and the result will always be a list of DOM trees. Also, if fragment is True, if no_leading_text is True and the (X)HTML begins by a text instead of a node, this text is removed.
- parse_htmlstring(self, text, fragment=False, no_leading_text=False, xhtml=False) -- as parse_html() but the (X)HTML is read from the text string.
Head renderer
The head attribute of a XHTML renderer is a Head renderer, an instance of the class HeadRenderer of namespaces/xhtml.py#xhtml.HeadRenderer.
A head renderer is a factory for all the XHTML tags that can be embedded into the <head> section: base, head, link, meta, title, style and script:
from nagare import presentation
class App:
pass
@presentation.render_for(App):
def render(self, h, *args):
# h.head is a Head renderer
h.head << h.head.title('My Application')
return h.div(h.h1('Hello world !'))
A head renderer has also the following method:
css(self, name, style) -- add a css style definition. The style must be named so that, if added by several views, it will be included only once in the generated page.
@presentation.render_for(App): def render(self, h, *args): h.head.css('main_content', '.main { border: 1px red solid }') return h.div(h.h1('Hello world !'), class_='main')css_url(self, url) -- add a css url. If the url is relative, it's relative to the static directory of the application (see ApplicationConfiguration)
@presentation.render_for(App): def render(self, h, *args): h.head.css_url('http://www.nagare.org/site.css') # Absolute URL h.head.css_url('css/my_application.css') # Relative URL return h.div(h.h1('Hello world !'), class_='main')javascript(self, name, script) -- add a javascript definition. The javascript code must be named so that, if added by several views, it will be included only once in the generated page.
@presentation.render_for(App): def render(self, h, *args): h.head.javascript('debug', 'function debug(msg) { alert(msg) }') return h.div(h.h1('Hello world !'), class_='main')javascript_url(self, url) -- add a javascript url. If the url is relative, it's relative to the static directory of the application (see ApplicationConfiguration)
@presentation.render_for(App): def render(self, h, *args): h.head.javascript_url('http://www.nagare.org/anim.js') # Absolute URL h.head.javascript_url('js/debug.js') # Relative URL return h.div(h.h1('Hello world !'), class_='main')
After the rendering phase, Nagare generates a <head> section which is the concatenation of all the DOM objects the different views have put into the Head renderer.
XML renderer
A XML renderer is an instance of the Renderer class of namespaces/xml.py#xml.Renderer.
It's a simple renderer which accepts any tag creation:
>>> from nagare.namespaces import xml >>> x = xml.Renderer() >>> tree = x.contact(x.name('John Doe'), x.age(20)) >>> tree.write_xmlstring() '<contact><name>John Doe</name><age>20</age></contact>'
XSL renderer
A XSL renderer is an instance of the Renderer class of namespaces/xsl.py#xsl.Renderer and has a factory for all the possible XSL tags.
ESI renderer
A ESI renderer is an instance of the Renderer class of namespaces/esi.py#esi.Renderer and has a factory for all the possible ESI tags : attempt, choose, comment, include, inline, otherwise, remove, try, vars, when.
Namespaces and renderers mixin
A renderer can create DOM object in a specific XML namespace. First the namespace(s) must be declared to the renderer by setting its namespaces attribute to a namespace prefix -> namespace uri dictionary. Then, at any moment, the namespace to use is choosen by setting its default_namespace atttribut to the prefix of the namespace:
>>> from nagare.namespaces import xsl
>>> x = xsl.Renderer()
>>> x.namespaces = { 'xsl' : 'http://www.w3.org/1999/XSL/Transform' }
>>> x.default_namespace = 'xsl'
>>> xsl = x.stylesheet(
... x.output(encoding="utf-8"),
... x.template(
... x.copy_of(select="."),
... match="/"
... )
... )
>>> print xsl.write_xmlstring(pretty_print=True)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8"/>
<xsl:template match="/">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Different renderers, with different namespaces, can be combinated to build a DOM tree:
>>> from nagare.namespaces import xhtml, esi
>>> h = xhtml.Renderer()
>>> s = esi.Renderer()
>>> s.namespaces = { 'esi': esi.NS }
>>> s.default_namespace = 'esi'
>>> tree = h.html(
... h.body(
... h.h1('Hello'),
... s.include(src='http://www.nagare.org'),
... h.p('world')
... )
... )
>>> print tree.write_xmlstring(pretty_print=True)
<html>
<body>
<h1>Hello</h1>
<esi:include xmlns:esi="http://www.edge-delivery.org/esi/1.0" src="http://www.nagare.org"/>
<p>world</p>
</body>
</html>