[Solved] Is it possible to use datagridfield in a behavior? Yes!

I'm currently working on a behavior which should collect a list of items, with additional configuration. Therefor a DGF (DataGRidField) would be optimal (or a multiwidget).

Before I post all the code, is it possible to use multi widgets like DGF in behaviors?

So here is the example code:

# -*- coding: utf-8 -*-
"""DGF Behavior Test."""

from collective.z3cform.datagridfield import DataGridFieldFactory
from collective.z3cform.datagridfield import DictRow
from plone.autoform import directives
from plone.autoform.interfaces import IFormFieldProvider
from plone.dexterity.interfaces import IDexterityContent
from plone.supermodel import model
from zope import schema
from zope.component import adapter
from zope.interface import implementer
from zope.interface import provider


class IDGFSchema(model.Schema):
    """DGF schema."""
    field_1 = schema.TextLine(
        required=False,
        title=u'Field 1',
    )

    field_2 = schema.TextLine(
        required=False,
        title=u'Field 2',
    )


@provider(IFormFieldProvider)
class IDGFBehaviorSchema(model.Schema):
    """DGF behavior schema."""

    directives.widget(
        'dgf_field',
        DataGridFieldFactory,
        allow_reorder=True,
    )
    dgf_field = schema.List(
        required=False,
        title=u'DGF Example field',
        value_type=DictRow(
            title=u'DGF Row',
            schema=IDGFSchema,
        ),
    )


@implementer(IDGFBehaviorSchema)
@adapter(IDexterityContent)
class DGFBehaviorSchema(object):

    def __init__(self, context):
        self.context = context

And it is registered as a behavior:

  <plone:behavior
      description="Example DGF behavior."
      factory=".dgfbehavior.DGFBehaviorSchema"
      for="plone.dexterity.interfaces.IDexterityContent"
      marker=".dgfbehavior.IDGFBehaviorSchema"
      provides=".dgfbehavior.IDGFBehaviorSchema"
      title="DGF Behavior"
      />

When enabling the behavior and editing content, this is the traceback I get:

Traceback (innermost last):
  Module ZPublisher.WSGIPublisher, line 155, in transaction_pubevents
  Module ZPublisher.WSGIPublisher, line 337, in publish_module
  Module ZPublisher.WSGIPublisher, line 255, in publish
  Module ZPublisher.mapply, line 85, in mapply
  Module ZPublisher.WSGIPublisher, line 61, in call_object
  Module plone.z3cform.layout, line 63, in __call__
  Module plone.z3cform.layout, line 57, in update
  Module z3c.form.form, line 162, in render
  Module zope.browserpage.viewpagetemplatefile, line 49, in __call__
  Module zope.pagetemplate.pagetemplate, line 135, in pt_render
  Module Products.PageTemplates.engine, line 88, in __call__
  Module z3c.pt.pagetemplate, line 173, in render
  Module chameleon.zpt.template, line 306, in render
  Module chameleon.template, line 187, in render
  Module c6a1b46627165c993a1edccc49eceabc.py, line 101, in render
  Module bbcb86e64e8b16f10f9de68e5ad1a2d5.py, line 764, in render_titlelessform
  Module bbcb86e64e8b16f10f9de68e5ad1a2d5.py, line 1026, in render_fields
  Module bbcb86e64e8b16f10f9de68e5ad1a2d5.py, line 1497, in render_widget_rendering
  Module bbcb86e64e8b16f10f9de68e5ad1a2d5.py, line 1591, in render_field
  Module Products.PageTemplates.expression, line 101, in __call__
  Module zope.browserpage.simpleviewclass, line 41, in __call__
  Module zope.browserpage.viewpagetemplatefile, line 81, in __call__
  Module zope.browserpage.viewpagetemplatefile, line 49, in __call__
  Module zope.pagetemplate.pagetemplate, line 135, in pt_render
  Module Products.PageTemplates.engine, line 88, in __call__
  Module z3c.pt.pagetemplate, line 173, in render
  Module chameleon.zpt.template, line 306, in render
  Module chameleon.template, line 187, in render
  Module 1626b71c8c3264c64108b8959922fc58.py, line 628, in render
  Module 1626b71c8c3264c64108b8959922fc58.py, line 494, in render_widget_wrapper
  Module Products.PageTemplates.expression, line 101, in __call__
  Module z3c.form.widget, line 154, in render
  Module zope.browserpage.viewpagetemplatefile, line 49, in __call__
  Module zope.pagetemplate.pagetemplate, line 135, in pt_render
  Module Products.PageTemplates.engine, line 88, in __call__
  Module z3c.pt.pagetemplate, line 173, in render
  Module chameleon.zpt.template, line 306, in render
  Module chameleon.template, line 209, in render
  Module chameleon.utils, line 75, in raise_with_traceback
  Module chameleon.template, line 187, in render
  Module d01dc7cbb6bb2281275cb9b841067789.py, line 940, in render
  Module d01dc7cbb6bb2281275cb9b841067789.py, line 133, in render_widget_row
IndexError: list index out of range

 - Expression: "et python:view.key_widgets[repeat['widget'].index"
 - Filename:   ... 1.1-py3.7.egg/plone/app/z3cform/templates/multi_input.pt
 - Location:   (line 7: col 33)
 - Source:     ... ey_widget python:view.key_widgets[repeat['widget'].index()];
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 - Expression: "widget/render"
 - Filename:   ... rm-3.1.1-py3.7.egg/plone/app/z3cform/templates/widget.pt
 - Location:   (line 39: col 46)
 - Source:     ... xt" tal:replace="structure widget/render"
                                              ^^^^^^^^^^^^^
 - Expression: "widget/@@ploneform-render-widget"
 - Filename:   ... rm-3.1.1-py3.7.egg/plone/app/z3cform/templates/macros.pt
 - Location:   (line 100: col 81)
 - Source:     ... place="structure widget/@@ploneform-render-widget"/>
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 - Expression: "context/@@ploneform-macros/titlelessform"
 - Filename:   ... 1.0-py3.7.egg/plone/z3cform/pagetemplates/wrappedform.pt
 - Location:   (line 1: col 22)
 - Source:     ... e use-macro="context/@@ploneform-macros/titlelessform" />
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 - Arguments:  template: <ViewPageTemplateFile - at 0x1147eb890>
               options: {...} (0)
               args: <tuple - at 0x108667050>
               nothing: <NoneType - at 0x108578118>
               modules: <TraversableModuleImporter - at 0x10b752d10>
               request: <WSGIRequest - at 0x115607b90>
               view: <DataGridField IDGFBehaviorSchema.dgf_field at 0x114fe6950>
               context: <DraftProxy draft at 0x11558e990>
               views: <ViewMapper - at 0x1150a8190>
               default: <object - at 0x10965df60>
               repeat: {...} (0)
               loop: {...} (1)
               wrapped_repeat: {...} (1)
               target_language: <NoneType - at 0x108578118>
               translate: <function translate at 0x115484830>
               widget: <DataGridFieldObject None at 0x114b0c1d0>

I'm using Plone 5.2 on Python 3.7.4 for this.

Solved, I somehow missed to install DGF and assumed it was already :man_facepalming:

2 Likes