(ポートレット)

Description

How to create and subclass portlets in Plone. How to look-up and modify portlets on the site programmatically.

ポートレットを作成する

  • You need a paster-compatible product skeleton created using paster create -t plone or paster create -t archetypes commands.
  • Use project specific paster command paster addcontent portlet to create a code skeleton for your new portlet.

Subclassing a portlet

You can subclass a portlet to create a new portlet type with your enhanced functionality.

Overriding portlet rendering

Use <plone:portletRenderer> directive. Specify 1) layer, 2) template and/or 3) class 4) portlet interface.

You need <include package=""> directive for the package whose portlet you are going to override.

<configure
    xmlns:plone="http://namespaces.plone.org/plone"
    >

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

        <plone:portletRenderer
           portlet="plone.app.portlets.portlets.news.INewsPortlet"
           template="mytheme_news.pt"
           layer=".interfaces.IThemeSpecific"
           />

</configure>

More information

available property

The portlet renderer can define available property to hint the portlet manager when the portlet should be rendered.

Example

class Renderer(base.Renderer):

    @property
    def available(self):
        # Show this portlet for logged in users only
        return not self.anonymous

Iterate portlets assigned to the portal root

Below is an simple example how to print all portlets which have been assigned to the portal root:

def check_root_portlets(self):
    """ Print all portlet assignments in the portal root """

    from zope.component import getUtility, getMultiAdapter
    from plone.portlets.interfaces import IPortletManager
    from plone.portlets.interfaces import IPortletAssignment
    from plone.portlets.interfaces import IPortletAssignmentMapping

    content = self.portal

    for manager_name in [ "plone.leftcolumn", "plone.rightcolumn" ]:

        print "Checking portlet column:" + manager_name

        manager = getUtility(IPortletManager, name=manager_name, context=content)

        mapping = getMultiAdapter((content, manager), IPortletAssignmentMapping)

        # id is portlet assignment id
        # and automatically generated
        for id, assignment in mapping.items():
            print "Found portlet assignment:" + id + " " + str(assignment)

Walking through every portlet on the site

The following code iterates through all portlets assigned directly to content items. This excludes dashboard, group and content type based portlets. Then it prints some info about them and renders them.

Example code:

from Products.Five.browser import BrowserView

from zope.component import getUtility, getMultiAdapter
from zope.app.component.hooks import setHooks, setSite, getSite

from plone.portlets.interfaces import IPortletType
from plone.portlets.interfaces import IPortletManager
from plone.portlets.interfaces import IPortletAssignment
from plone.portlets.interfaces import IPortletDataProvider
from plone.portlets.interfaces import IPortletRenderer
from plone.portlets.interfaces import IPortletAssignmentMapping
from plone.portlets.interfaces import ILocalPortletAssignable

from Products.CMFCore.interfaces import IContentish

class FixPortlets(BrowserView):
        """ Magical portlet debugging view """

        def __call__(self):
            """
            """

            request = self.request

            portal = getSite()

            # Not sure why this is needed...
            view = portal.restrictedTraverse('@@plone')

            # Query all content items on the site which can get portlets assigned
            # Note that this should excule special, hidden, items like tools which otherwise
            # might appearn in portal_catalog queries
            all_content = portal.portal_catalog(show_inactive=True, language="ALL", object_provides=ILocalPortletAssignable.__identifier__)

            # Load the real object instead of index stub
            all_content = [ content.getObject() for content in all_content ]

            # portal itself does not show up in the query above,
            # though it might contain portlet assignments
            all_content = list(all_content) + [portal]

            for content in all_content:

                    for manager_name in [ "plone.leftcolumn", "plone.rightcolumn" ]:

                            manager = getUtility(IPortletManager, name=manager_name, context=content)

                            mapping = getMultiAdapter((content, manager), IPortletAssignmentMapping)

                            # id is portlet assignment id
                            # and automatically generated
                            for id, assignment in mapping.items():
                                    print "Found portlet assignment:" + id + " " + str(assignment)

                                    renderer = getMultiAdapter((content, request, view, manager, assignment), IPortletRenderer)

                                    # Renderer acquisition chain must be set-up so that templates
                                    # et. al. can resolve permission inheritance
                                    renderer = renderer.__of__(content)

                                    # Seee http://svn.zope.org/zope.contentprovider/trunk/src/zope/contentprovider/interfaces.py?rev=98212&view=auto
                                    renderer.update()
                                    html = renderer.render()
                                    print "Got HTML output:" + html


            return "OK"

For more information about portlet assignments and managers, see

Checking if a certain context portlet is active on a page

  • Iterate through portlet managers by name
  • Get portlet retriever for the manager
  • Get portlets
  • Check if the portlet assignment provides your particular portlet marker interface

Example:

import Acquisition
from zope.component import getUtility, getMultiAdapter


from plone.portlets.interfaces import IPortletRetriever, IPortletManager

for column in ["plone.leftcolumn", "plone.rightcolumn"]:

    manager = getUtility(IPortletManager, name=column)

    retriever = getMultiAdapter((self.context, manager), IPortletRetriever)

    portlets = retriever.getPortlets()

    for portlet in portlets:

        # portlet is {'category': 'context', 'assignment': <FacebookLikeBoxAssignment at facebook-like-box>, 'name': u'facebook-like-box', 'key': '/isleofback/sisalto/huvit-ja-harrasteet
        # Identify portlet by interface provided by assignment
        if IFacebookLikeBoxData.providedBy(portlet["assignment"]):
            return True

return False