Hi Martin,
(Re-awakening an old thread...)
Thanks for your reply before. I'm afraid I'm only just getting back to
this issue...
Martin Aspeli wrote:
Tim Hicks wrote:
Hi (Martin),
Is it possible to assign a selection of portlets to a specific
interface, rather than a specific content type? That is, can I do
something like the following, where INTERFACE_CATEGORY has been
substituted in for CONTENT_TYPE_CATEGORY?
from plone.portlets.constants import INTERFACE_CATEGORY
left_column = getUtility(IPortletManager, name="plone.leftcolumn")
left_category = left_column[INTERFACE_CATEGORY]
left_portlets = left_category.get('Weblog', None)
# It may be that it hasn't been created yet, so just to be safe:
if left_portlets is None:
left_category[my_interfaces_dotted_name] =
PortletAssignmentMapping()
left_portlets = left_category[my_interfaces_dotted_name]
for name, assignment, kwargs in DEFAULT_LEFT_PORTLETS:
if not left_portlets.has_key(name):
left_portlets[name] = assignment(**kwargs)
An IPortletRetriever is used to pick the portlets to be returned. It
asks an IPortletContext what the "current" cateogories and their values
are - so, we may return a tuple like ((CONTENT_TYPE_CATEGORY,
'Document',), (GROUP_CATEGORY, 'MyGroup',), (GROUP_CATEGORY,
'MyOtherGroup')). It then uses the category + value (in the order given)
to look up global portlet assignments in an IPortletManager.
Ok, so I've tried to override the standard IPortletContext with my own
that additionally returns an 'interface_category' category. It looks
(approximately) like this:
class WeblogAwarePortletContext(ContentContext):
"""
"""
implements(IPortletContext)
adapts(Interface, ISiteRoot)
def globalPortletCategories(self, placeless=False):
cats = super(ContentContext,
self).globalPortletCategories(placeless)
ifaces = self._getInterfaces()
for iface in ifaces:
cats.append(INTERFACE_CATEGORY, iface.__identifier__)
def _getInterfaces(self):
if IWeblog.providedBy(self.context):
return [IWeblog,]
if IWeblogEnhanced.providedBy(self.context):
return [IWeblogEnhanced,]
return [Interface,]
In my overrides.zcml file (which is explicitly invoked from an
overrides.zcml in my Products.QuillsEnabled package), I have the following:
<configure xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:plone="http://namespaces.plone.org/plone">
<!-- Set up the portlet context -->
<adapter factory=".context.WeblogAwarePortletContext" />
</configure>
However, when I try to assign some specific portlets to this category, I
get a KeyError on my value for INTERFACE_CATEGORY (i.e.
'interface_category'). Specifically, I try:
def weblogPortletSetup(portal,
out,
ifaces=[IWeblog, IWeblogEnhanced]):
left_column = getUtility(IPortletManager, name="plone.leftcolumn")
left_category = left_column[INTERFACE_CATEGORY]
... and get the KeyError on that last line.
One clue about why this isn't working is that adding an "import pdb;
pdb.set_trace()" to the first line of my globalPortletCategories method
reveals that it never gets called. So, it looks like I haven't got
something registered properly. Any clues?
So yes - you can define new categories, and you can use the dict-like
semantics of an IPortletManager to store them. The README.txt in
plone.portlets (not plone.app.portlets) will tell you more about how
this works.
Ok.
Another thing you may want to think about is to use a more global
portlet assignment category, but to register different
IPortletRenderer's for different context interfaces. That way, you can
use the same assignment but vary the rendering by interface (including
local markers, of course).
IIUC, this is the approach that I am taking. I trying to register a
general IPortletContext that gives a new 'interface_category' category.
Then I use that same IPortletContext to decide which interfaces are
relevant for the portlet lookup (i.e. with my _getInterfaces method).
I'm not sure if this is really the best way of approaching this, however.
Would it make sene for the core plone.app.portlets code to provide an
INTERFACE_CATEGORY ootb? That way, there could be a simple api for
registering portlets per interface. Something like:
from plone.app.portlets import registerPortletForInterface
registerPortletForInterface(a_portlet_assignment, IMyInterface)
Based on those registrations, code in plone.app.portlets would then
return a list of portlet assignments for each interface implemented by
the context object.
Just a thought.
Tim
_______________________________________________
Product-Developers mailing list
[email protected]
http://lists.plone.org/mailman/listinfo/product-developers