diff -r 1de74ac0628f -r 31b3d00edb8a src/source/developer_guide/tales.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/source/developer_guide/tales.rst Tue Dec 11 16:29:56 2018 +0100 @@ -0,0 +1,74 @@ +.. _tales: + +Custom TALES extensions +======================= + +PyAMS defines a custom expression for TALES called *extension*. + +When this expression is encountered, the renderer is looking for an +:py:class:`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 :py:func:`render` method with +the expression parameters as input parameters. + +For example, the *metas* extension is an *ITALESExtension* adapter defined into +:py:mod:`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: + +.. code-block:: html + + + +This extension is defined like this: + +.. code-block:: python + + 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: + +.. code-block:: html + + + + + +The extension is defined like this: + +.. code-block:: python + + 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)