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