March 6 2008posted by Santi

Render widgets from own code

CPSSchema's allows to render automatic pages for edit, create or view objects, based on defined portal_layouts. But, how we can render directly the widgets in theese layouts, so we can write our own page template ?  Using KMKey it's simple, just inherit your view from Products.KMKeyCore.baseview.KMKeyBaseView, and use the renderWidget function:

  
    def renderWidget(self, layout_id, widget_id, proxy=None, content=None,
                     portal_type=None, mode='view'):
        """
        Function to render a specific widget
          - layout_id and widget_id are mandatories
          - if proxy or content aren't None, then use them to obtain a datamodel
          - Either, portal_type should be passed to obtain an empty datamodel
          - mode could be 'view' or 'edit'
        """

Used from a page template this way:

    <div tal:content="structure python:view.renderWidget(layout_id='metadata', widget_id='w__Description', proxy=item)" />


If you prefer do it yourself, you can use something like this:

    from Products.CPSSchemas.DataStructure import DataStructure

    mode = 'edit' # Could also be 'view'
    portal_type = 'KMKey Project'  # The portal_type ID from portal_types
    layout = 'kmkey_planning'
    widget_id = 'w__end'

    dm = cps.portal_types[portal_type].getDataModel(None)
    ds = DataStructure(dm, datamodel=dm)

    widget = cps.portal_layouts[layout][widget_id]
    widget.prepare(ds)
    widget.render(mode, ds)


The previous code works to obtain an empty widget.   If we want to obtain the widget filled with data of an existing object, we simply should obtain its datamodel:

    dm = proxy.getContent().getDataModel()