.. We set up the skin components from the getting started section .. behind the scenes. >>> _ = xmlconfig(""" ... ... ... ... ... ... ... ... ... ... ... """.strip() % locals()) Templates ========= Included with the package is a factory for Zope Page Templates (with the file extension ".pt"). The :mod:`Chameleon` engine is used to render templates. Page templates registered as skin objects will be called *skin templates*. Support is provided to locate other skin templates and include them as macros. Skin expression ############### This package provides a new expression ``skin:`` which will retrieve a skin object by name:: tal:define="inst skin: /main_template" .. -> define_main_template The pipe operator lets us provide one or more fallback options:: tal:define="inst skin: /images/logo.gif | skin: /images/logo.png" .. -> define_logo >>> def render_template(string, **context): ... from tempfile import NamedTemporaryFile ... f = NamedTemporaryFile(suffix=".pt") ... f.write(string) ... f.flush() ... from pyramid_skins.zcml import register_skin_object ... register_skin_object(registry, string, f.name, None) ... from pyramid_skins import SkinObject ... inst = SkinObject(string) ... try: ... return inst(**context).body ... finally: ... f.close() >>> template = "
" >>> print render_template(template % define_main_template) /.../skins/main_template.pt >>> print render_template(template % define_logo) /.../skins/images/logo.png Whitespace is ignored in any case. Skin lookups are either absolute or relative. *Absolute* If the name begins with a slash ("/") character, it's considered an absolute lookup, e.g.:: /images/logo.png => "images/logo.png" This is a placeless lookup. *Relative* If the name does not begin with a slash, it is a placeful lookup. Descending from the current path (given a skin template context), we attempt to locate the skin object at every parent level. For example, the name ``"images/logo.png"`` is relative. If we are rendering the about page, then it will map to:: /about/images/logo.png instead of:: /images/logo.png This is similar to *acquisition* (the object is attempted acquired from the current context and below). It can be used to redefine skin objects for a particular location and below. >>> from zope.component import getUtility >>> from pyramid_skins.interfaces import ISkinObject >>> about = getUtility(ISkinObject, name="about/index") >>> print about(context=u"Hello world!").body ... ... Finally, skins may also be request-specific. In the setup for this test, we have registered an alternative skins directory for the standard ``IRequest`` layer. The standard dummy request provides this layer: >>> from pyramid_skins.tests import IAlternativeRequest >>> from zope.interface import alsoProvides >>> alsoProvides(request, IAlternativeRequest) We can now see that the 'main_template' skin object is resolved from the skins path registered for the ``IRequest`` layer (``"alt_skins"``): >>> print render_template(template % define_main_template) /.../alt_skins/main_template.pt This applies also to the ``SkinObject`` constructor: >>> from pyramid_skins import SkinObject >>> bound = SkinObject("main_template").__get__() >>> response = bound() >>> print response.body Alternative Hello template! Remove request again. >>> from zope.interface import noLongerProvides >>> noLongerProvides(request, IAlternativeRequest) Route expression ################ The ``route:`` expression maps to the ``pyramid.url.route_url`` framework function:: .. -> source In the :ref:`framework integration ` section we learn how you can set up a route to serve up skin objects as static resources or even views. >>> from pyramid.testing import registerRoute >>> route = registerRoute("/static", "static") >>> print render_template(source) This is a convenient way to compute the URL for static resources. See the `Pyramid url documentation `_ for more information on URL generation. Macro support ############# Skin templates may define macros. Use the standard ``macros`` attribute to reach them:: Inserted. .. -> source >>> print render_template(source) Inserted. Skin objects can also be used directly as METAL macros. In this case the entire template is rendered:: Inserted. .. -> source >>> print render_template(source) Inserted.