-
how to create a tales namespace
last modified July 21 by rmarianski
In tal, you can create your own custom namespace, which you can call directly in tal. This is a powerful, clean way to reuse code among various templates.
First, an example to give you an idea of what you can use for this:
<span tal:replace="context/modified/dateutils:long">Tuesday - Jul 15, 2008</span>
<span tal:replace="context/modified/dateutils:short">07/15/2008</span>
And you get that without having to *anything* in your template. No creating of a view method, inheriting from some base class, relying on acquisition, nothing.
This is implemented as a named adapter under the hood. In the example above, the datetime (context/modified) is the context, the name is "dateutils", and "long"/"short" are methods called on the adapter. Here's what the implementation might look like:
from zope.traversing.interfaces import IPathAdapter
from zope.tales.interfaces import ITALESFunctionNamespace
from zope import interface
from zope import component
class DateUtils(object):
component.adapts(interface.Interface)
interface.implements(ITALESFunctionNamespace, IPathAdapter)
def __init__(self, context):
if callable(context):
self.context = context()
else:
self.context = context
def long(self):
return self.context.strftime('%A - %b %d, %Y')
def short(self):
return self.context.strftime('%m/%d/%y')
def setEngine(self, engine):
pass
Then we need to wire it up through zcml.
<adapter
for="*"
provides="zope.traversing.interfaces.IPathAdapter"
factory=".dateutils.DateUtils"
name="dateutils"
trusted="true"
/>
<content class=".dateutils.DateUtils">
<require permission="zope2.View"
attributes="setEngine long short" />
</content>
Note that when you add a new method, you have to add the attribute in zcml, or you'll get a traversal error.
Alternatively, you can create a new interface to represent your new functions, implement that interface, and then your zcml is as follows;
<content class=".dateutils.DateUtils">
<require permission="zope2.View"
interface="IDateUtils" />
</content>
And I'll finish with a caveat. There are times when creating your own tales functions makes a lot of sense. There are more times when it doesn't. Only use this abstraction when you have a great many unrelated templates that share the same basic logic. Great candidates are general "utility" functions.