开发者

plone:portlet vs plone:portletRenderer (subclassing problem)

A oddity we tripped across when upgrading sites from Plone 3 to Plone 4:

We define a number of custom portlets. One of these is a "Jobs" portlet which is a lightly customised News Portlet. This was subclassed from the News portlet, as suggested by:

http://plone.org/documentation/manual/developer-manual/portlets/appendix-practicals/subclassing-new-portlets.

That is:

<plone:portlet
  name="falcon.JobsPortlet"
  interface=".portlets.IFalconJobsPortlet"
   ...
  renderer=".portlets.FalconJobsRenderer"
 />

where IFalconJobsPortlet subclasses from INewsPortlet:

from plone.app.portlets.portlets.news import INewsPortlet

class IFalconJobsPortlet(INewsPortlet):
 """Interface for Jobs portlet uses the same schema as News Portlet"""

We also (separately) want to replace the render class on the standard INewsPortlet, in order to provide a custom template:

<plone:portletRenderer
   portlet="plone.app.portlets.portlets.news.INewsPortlet"
   class=".portlets.FalconNewsRenderer"
   layer=".interfaces.IThemeSpecific"
   />

This works fine in Plone 3. This might just have been blind luck, or it might be case that <plone:portletRenderer> used to run before <plone:portlet>, and now run afterwards.

In Plone 4, falcon.JobsPortlet is set up correctly, but then <plone:portletRenderer> kicks in and replaces the renderer clause, so that

".portlets.FalconJobsRenderer" (correct)     is replaced with
".portlets.FalconNewsRenderer" (incorrect)

A solution/workaround in this case was simple: I stopped subclassing from INewsPortlet, and just copied the schema across by hand from the ori开发者_如何学JAVAginal superclass:

class IFalconJobsPortlet(IPortletDataProvider):
  """Interface for Jobs portlet uses the same schema as News Portlet"""
 count = ...
 state = ...

My question, for future reference:

Is there a way to safely combine <plone:portlet> and <plone:portletRenderer> when subclassed portlets are in play?


If you're not using layer="..." in your <plone:portlet name="falcon.JobsPortlet"...> registration, then this is probably the root. The ZCA, which this ZCML uses to register adapters, gives one lookup precedence over another based on interface specificity. So I'm guessing the since you give a layer in your <plone:portletRenderer> but not in your <plone:portlet> then the renderer in <plone:portletRenderer> matches the portlet interface of both and the layer is more specific and so it wins.

Since only <plone:portletRenderer> supports the layer specification, I would just add a <plone:portletRenderer> registration for the FalconJobsRenderer that is registered for the same layer and that will assure correct precedence. That way you can revert your workaround and subclass INewsPortlet. It is much more appropriate to subclass INewsPortlet.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜