src/source/dev_guide/tales.rst
branchdoc-dc
changeset 139 d632f8d6140b
parent 138 7205ae7c43dc
child 140 df3106def670
equal deleted inserted replaced
138:7205ae7c43dc 139:d632f8d6140b
     1 .. _tales:
       
     2 
       
     3 Custom TALES extensions
       
     4 =======================
       
     5 
       
     6 PyAMS defines a custom expression for TALES called *extension*.
       
     7 
       
     8 When this expression is encountered, the renderer is looking for an
       
     9 :py:class:`ITALESExtension <pyams_utils.interfaces.tales.ITALESExtension>`
       
    10 multi-adapter for the current *context*, *request* and *view*, for the current
       
    11 *context* and *request*, or only for the current *context*, in this order.
       
    12 If an adapter is found, the renderer call it's :py:func:`render` method with
       
    13 the expression parameters as input parameters.
       
    14 
       
    15 For example, the *metas* extension is an *ITALESExtension* adapter defined into
       
    16 :py:mod:`pyams_skin.metas` module which can be used to include all required headers in
       
    17 a page template. Extension is used like this in the page layout template:
       
    18 
       
    19 .. code-block:: html
       
    20 
       
    21     <tal:var replace="structure extension:metas" />
       
    22 
       
    23 This extension is defined like this:
       
    24 
       
    25 .. code-block:: python
       
    26 
       
    27     from pyams_skin.interfaces.metas import IHTMLContentMetas
       
    28     from pyams_utils.interfaces.tales import ITALESExtension
       
    29     from pyramid.interfaces import IRequest
       
    30 
       
    31     from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
       
    32 
       
    33     @adapter_config(name='metas', context=(Interface, IRequest, Interface), provides=ITALESExtension)
       
    34     class MetasTalesExtension(ContextRequestViewAdapter):
       
    35         '''extension:metas TALES extension'''
       
    36 
       
    37         def render(self, context=None):
       
    38             if context is None:
       
    39                 context = self.context
       
    40             result = []
       
    41             for name, adapter in sorted(self.request.registry.getAdapters((context, self.request, self.view),
       
    42                                                                           IHTMLContentMetas),
       
    43                                         key=lambda x: getattr(x[1], 'order', 9999)):
       
    44                 result.extend([meta.render() for meta in adapter.get_metas()])
       
    45             return '\n\t'.join(result)
       
    46 
       
    47 Some TALES extensions can require or accept arguments. For example, the *absolute_url* extension can accept
       
    48 a context and a view name:
       
    49 
       
    50 .. code-block:: html
       
    51 
       
    52     <tal:var define="logo config.logo">
       
    53         <img tal:attributes="src extension:absolute_url(logo, '++thumb++200x36.png');" />
       
    54     </tal:var>
       
    55 
       
    56 The extension is defined like this:
       
    57 
       
    58 .. code-block:: python
       
    59 
       
    60     from persistent.interfaces import IPersistent
       
    61     from pyams_utils.interfaces.tales import ITALESExtension
       
    62 
       
    63     from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
       
    64     from pyramid.url import resource_url
       
    65     from zope.interface import Interface
       
    66 
       
    67     @adapter_config(name='absolute_url', context=(IPersistent, Interface, Interface), provides=ITALESExtension)
       
    68     class AbsoluteUrlTalesExtension(ContextRequestViewAdapter):
       
    69         '''extension:absolute_url(context, view_name) TALES extension'''
       
    70 
       
    71         def render(self, context=None, view_name=None):
       
    72             if context is None:
       
    73                 context = self.context
       
    74             return resource_url(context, self.request, view_name)