Cannot get collective.z3cform.datagridfield to work on plone 5.2

I would like to use the collective.z3cform.datagridfield addon on a standalone form I'm writing on plone5.2 (python3), but I can't even get the sample code to run:

Here the code I used (imports are omitted) from README.rst:

interfaces.py

class ITableRowSchema(interface.Interface):
    one = schema.TextLine(title=u"One")
    two = schema.TextLine(title=u"Two")
    three = schema.TextLine(title=u"Three")

class IFormSchema(interface.Interface):
    four = schema.TextLine(title=u"Four")
    table = schema.List(title=u"Table",
        value_type=DictRow(title=u"tablerow", schema=ITableRowSchema))

browser/editform.py

@component.adapter(IFormSchema)
class EditForm(form.EditForm):

    fields = field.Fields(IFormSchema)
    label=u"Demo Usage of DataGridField"

    fields['table'].widgetFactory = DataGridFieldFactory

browser/configure.zcml

...

<browser:page
    name="editform--example"
    class=".editform.EditForm"
    for="*"
    permission="zope2.View"
    />

...

When I access the view through http://localhost:8080/mig/@@editform--example I keep getting the following error:

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 z3c.form.form, line 233, in __call__
Module z3c.form.form, line 226, in update
Module plone.z3cform.patch, line 20, in BaseForm_update
Module z3c.form.form, line 154, in update
Module z3c.form.form, line 136, in updateWidgets
Module z3c.form.field, line 243, in update
Module z3c.form.datamanager, line 102, in canWrite
Module z3c.form.datamanager, line 66, in adapted_context
TypeError: ('Could not adapt', <PloneSite at /mig>, <InterfaceClass my.formtest.interfaces.IFormSchema>)

What am I doing wrong?

1 Like

Did you install datagridfield in the add-on control panel ?

Thank you for answering @espenmn. Yes, I forgot to mention that I added datagridfield as a dependency on metadata.xml:

...
<dependencies>
    <dependency>profile-collective.z3cform.datagridfield:default</dependency>
</dependencies>
...

so it's installed automatically.

Davide

Did you try to specify the widget.
Something like:

from plone.autoform.directives import widget

widget(yourfield=DataGridFieldFactory)

Yes, I have tried previously with:

from plone.autoform import directives
...
directives.widget(table=DataGridFieldFactory)
    table = schema.List(title=u"Table",
        value_type=DictRow(title=u"tablerow", schema=ITableRowSchema))

Same error... :sob:

If you want to write a custom form, check this: https://docs.plone.org/develop/addons/schema-driven-forms/creating-a-simple-form/creating-the-form-view.html

Looking at the error this should probably work:

@component.adapter(IFormSchema)
class EditForm(form.EditForm):

    ignoreContext = True

The docs say:

We set ignoreContext to True. This tells z3c.form not to attempt to read the current value of any of the form fields from the context.

Thank you @csanahuja, that solved the problem! :+1: although now, when I fill the form, i get a validation error: "The system could not process the given value."

What are you trying to achieve with that custom form? What should the view do when you fill the form?

The example you posted alone does not make sense for me. I mean you are just rendering an Edit Form but there is no object where to save.

If you want to save the info you should create a Dexterity content type: https://docs.plone.org/external/plone.app.dexterity/docs/schema-driven-types.html

There is no object where to save because I don't need one.
What I am trying to achieve is a standalone form that sends an email or generates a pdf file (through reportlab for example) to be downloaded by the user who fills the form, so I don't need a persistent dexterity object.
My idea is to implement the email sending or the pdf file creation inside the form action (button). Something like:

 @button.buttonAndHandler(u"Submit")
 def handle_apply(self, action):
     data, errors = self.extractData()
     if errors:
         self.status = self.formErrorsMessage
         return
     
     // use form data to send an email or to generate a pdf file

    IStatusMessage(self.request).addStatusMessage(
        (u"Form submitted."),
        "info",
    )

     contextURL = self.context.absolute_url()
     self.request.response.redirect(contextURL)

Ok, I understand now try switching to:

class CustomForm(AutoExtensibleForm, form.Form):

    template = ViewPageTemplateFile('custom_form.pt')

    schema = IFormSchema
    ignoreContext = True

Where the template should render the form with
<metal:block use-macro="context/@@ploneform-macros/titlelessform" />

Like contact form is:


Let us now if the error it's still there

Unfortunately the problem persists. :cry:
I don't think that the error is due to a form rendering problem. The rendering was fine before.

I think I miss something with the validation for the datagridfield. The error is displayed when I put a value on the first field and I focus out of it. There is a call to http://localhost:8080/mig/@@editform--example/@@z3cform_validate_field that fails with: {"errmsg": "The system could not process the given value."}

This is a shot in the dark, but I remember that using datagridfield with a registry control panel I had to import slightly different:

from collective.z3cform.datagridfield.registry import DictRow

Yes, It's written in the readme of collective.z3cform.datagridfield, but I am not working with the registry nor with the controlpanel. This is a standalone form.

The interesting thing is that if I ignore the error on the datagrid field (The system could not process the given value) and submit the form, the values are correctly sent to the server and are present inside the data variable from extractData():

{'four': '000',
 'table': [
    {'one': '111', 'two': '222', 'three': '333'},
    {'one': '444', 'two': '555', 'three': '666'}
]}

:thinking:

The validation error seems to be raised only until the fields of one line are all filled with data.

scrrerecord

From the readme of collective.z3cform.datagridfield:

The DataGridField makes use of a subform to build each line.

The validation call to the server is made after the focus out of each field so I tried editing the subform interface and making all the fields optional:

class ITableRowSchema(interface.Interface):
    one = schema.TextLine(title=u"One", required=False)
    two = schema.TextLine(title=u"Two", required=False)
    three = schema.TextLine(title=u"Three", required=False)

And the error no longer shows up!

So that message is caused by a validation error on the form. The problem is that it's not very informative on which validation error occurred and on which field of the subform.
For example if I add a length constraint on the first field:

...
one = schema.TextLine(title=u"One", required=False, min_length=5)
...

and I add (in that field) a string shorter than five characters, the error is correctly displayed but always saying that the system could not process the given value.

I didn't understand if this is the desired behavior or a bug.

I had a same problem on Plone 5.2 (Python3) and I fixed it with this change.

Please refer it.

Hi @terapyon, this is not related to the issue I reported (which has to do with the validations).
The pull request you linked (if I understood correctly) solves the problem of the double new line on the datagridfield.

Plone Foundation Code of Conduct