plonezopeviewlets

Better way of tagging content types with a common interface


I want a viewlet to apply to the view of several content types in the same python egg. What I have been doing is applying the marker interface via browser/configure.zcml

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser"
    i18n_domain="AnnualProgramModule.content">

  <include package="plone.app.contentmenu" />

  <class class="..content.programyear.ProgramYear">
    <implements interface=".viewlets.IAnnualProgram" />
  </class>

  <class class="..content.institution.Institution">
    <implements interface=".viewlets.IAnnualProgram" />
  </class>

</configure>

And in my Grok-based template I have:

from zope.interface import Interface
from five import grok
from plone.app.layout.viewlets.interfaces import IAboveContentTitle
from AnnualProgramModule.content.interfaces import IInstitution

grok.templatedir('templates')

class IAnnualProgram(Interface):
    """Marker Interface for AnnualProgram content types
    """

class AnnualProgramViewlet(grok.Viewlet):
    grok.require('zope2.View')
    grok.viewletmanager(IAboveContentTitle)
    grok.context(IAnnualProgram)

class InstitutionViewlet(grok.Viewlet):
    grok.require('zope2.View')
    grok.context(IInstitution)
    grok.viewletmanager(IAboveContentTitle)

This works. But I am interested to know if there is a better way to do it.


Solution

  • No, what you are doing is actually the best way to approach this. Using marker interfaces is the way I would go about it in any case. :-)

    The alternative would be for you to re-register the viewlet for the interfaces or classes of all the different content types instead:

    <browser:viewlet
        name="yourpackage.annualprogram"
        for="..content.programyear.ProgramYear"
        manager="plone.app.layout.viewlets.interfaces.IAboveContentTitle"
        template="annualprogram.pt"
        permission="zope2.View"
        />
    
    <browser:viewlet
        name="yourpackage.annualprogram"
        for="..content.interfaces.IInstitution"
        manager="plone.app.layout.viewlets.interfaces.IAboveContentTitle"
        template="annualprogram.pt"
        permission="zope2.View"
        />
    

    but that is a whole lot more verbose.