Custom TALES extensions

PyAMS defines a custom expression for TALES called extension.

When this expression is encountered, the renderer is looking for an ITALESExtension multi-adapter for the current context, request and view, for the current context and request, or only for the current context, in this order. If an adapter is found, the renderer call it’s render() method with the expression parameters as input parameters.

For example, the metas extension is an ITALESExtension adapter defined into pyams_skin.metas module which can be used to include all required headers in a page template. Extension is used like this in the page layout template:

<tal:var replace="structure extension:metas" />

This extension is defined like this:

from pyams_skin.interfaces.metas import IHTMLContentMetas
from pyams_utils.interfaces.tales import ITALESExtension
from pyramid.interfaces import IRequest

from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter

@adapter_config(name='metas', context=(Interface, IRequest, Interface), provides=ITALESExtension)
class MetasTalesExtension(ContextRequestViewAdapter):
    '''extension:metas TALES extension'''

    def render(self, context=None):
        if context is None:
            context = self.context
        result = []
        for name, adapter in sorted(self.request.registry.getAdapters((context, self.request, self.view),
                                                                      IHTMLContentMetas),
                                    key=lambda x: getattr(x[1], 'order', 9999)):
            result.extend([meta.render() for meta in adapter.get_metas()])
        return '\n\t'.join(result)

Some TALES extensions can require or accept arguments. For example, the absolute_url extension can accept a context and a view name:

<tal:var define="logo config.logo">
    <img tal:attributes="src extension:absolute_url(logo, '++thumb++200x36.png');" />
</tal:var>

The extension is defined like this:

from persistent.interfaces import IPersistent
from pyams_utils.interfaces.tales import ITALESExtension

from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
from pyramid.url import resource_url
from zope.interface import Interface

@adapter_config(name='absolute_url', context=(IPersistent, Interface, Interface), provides=ITALESExtension)
class AbsoluteUrlTalesExtension(ContextRequestViewAdapter):
    '''extension:absolute_url(context, view_name) TALES extension'''

    def render(self, context=None, view_name=None):
        if context is None:
            context = self.context
        return resource_url(context, self.request, view_name)