• 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.