How can I properly hide Start/End fields from IEventBasic? extractData() is failing in Edit form

I apologize if this is a duplicate, but I'm getting an error with my edit form when I try to hide fields.
I believe that I am doing it the wrong way because of an error I am getting with extractData in my edit form.

In my mytype.py file:

from zope import schema
import z3c.form.interfaces
from z3c.form import button
from plone.dexterity.browser import add, edit
from plone.directives import form

class IMyType(form.Schema):
    e_start = schema.Date(title=u'Entry Date",
                                     required=True,
                                   )
   
    e_duration = schema.Float(title=_(u'Event Duration'),
                                           description=_(u'Duration by half hours'),
                                           required=True, 
                                    )


class AddForm(add.DefaultAddForm):

    portal_type='my.product.mycontenttype'
    template = ViewPageTemplateFile("templates/mycontenttype_add.pt")
    def __init__(self,context,request):
        super(AddForm, self).__init__(context, request, ti=None)

    def updateWidgets(self):
        super(AddForm, self).updateWidgets()      
  
        self.widgets["IEventBasic.start"].mode = z3c.form.interfaces.HIDDEN_MODE
        self.widgets["IEventBasic.end"].mode = z3c.form.interfaces.HIDDEN_MODE
        self.widgets["IEventBasic.open_end"].mode = z3c.form.interfaces.HIDDEN_MODE
        self.widgets["IEventBasic.whole_day"].mode = z3c.form.interfaces.HIDDEN_MODE
    
    @button(buttonAndHandler(_(u'Save'),name='save')
    data, errors = self.extractData()

        if errors:
            self.status = self.formErrorsMessage
            return
        obj = self.createAndAdd(data)

       #Back to container it was added
        self.request.response.redirect(self.context.absolute_url()) 

class AddView(add.DefaultAddView):
    form = AddForm

class EditForm(edit.DefaultEditForm):
    template = ViewPageTemplateFile("templates/mycontenttype_edit.pt")

    def updateWidgets(self):
        super(EditForm, self).updateWidgets()

        self.widgets["IEventBasic.start"].mode = z3c.form.interfaces.HIDDEN_MODE
        self.widgets["IEventBasic.end"].mode = z3c.form.interfaces.HIDDEN_MODE
        self.widgets["IEventBasic.whole_day"].mode = z3c.form.interfaces.HIDDEN_MODE
        self.widgets["IEventBasic.open_end"].mode = z3c.form.interfaces.HIDDEN_MODE
    
    @button.buttonAndHandler(_(u'Save'), name='save')
    def handleApply(self, action):
        data, errors = self.extractData()
        # ... breaks here

This is the error message I get when I edit and submit the form:

Traceback (innermost last):
    Module ZPublisher.Publish, line 138, in publish
    Module ZPublisher.mapply, line 77, in mapply
    Module ZPublisher.Publish, line 48, in call_object
    Module z3c.form.form, line 233, in __call__
    Module plone.dexterity.browser.edit, line 64, in update
    Module plone.z3cform.fieldsets.extensible, line 59, in update
    Module plone.z3cform.patch, line 30, in GroupForm_update
    Module z3c.form.group, line 145, in update
    Module plone.app.z3cform.csrf, line 21, in execute
    Module z3c.form.action, line 98, in execute
    Module z3c.form.button, line 315, in __call__
    Module z3c.form.button, line 170, in __call__
    Module my.product.mycontenttype, line 186, in handleApply
    Module z3c.form.group, line 114, in applyChanges
    Module z3c.form.form, line 47, in applyChanges
    Module z3c.form.util, line 183, in changedField
TypeError: can't compare offset-naive and offset-aware datetimes

When I did some searching through in z3c.form.form.util, it was breaking when it was checking to see if my event_field was not equal to its original value. For some reason, despite being a date field, e_start's old value was a datetime with an offset +5:00 hours while the new value was a datetime, but no offset was added.

When I didn't try hiding the event basic fields, it was working fine.

So I assume that something is conflicting when I try setting the mode to HIDDEN_MODE. What is the appropriate way of hiding these fields?

What I am trying to do has a purpose. I am using start and end for querying purposes, which are set parameters are set in added and modified events.

Edit: I am using the name e_start. This is because I am using zettwerk.fullcalendar and made it so that the first field ending with 'start' is targeted.

In principle, there should not be an important difference between the handling for a hidden field versus the handling for a "normal" field: in the first case, the value is placed in a "hidden" form control; in the second case in a shown and editable form control - apart from that, the conversion from the internal value to the external representation and back should in both cases be identical. The case may be different for a complex (editable) presentation, e.g. via a JS calendar view for a date field. Such a complex widget may use separate logic for the hidden and unhidden mode -- and the hidden mode logic can have a bug.

1 Like

@Kirtap - I don't see the relationship between your Schema and IEventBasic - are you providing that behavior for your type?
Your traceback shows that there are dates involved, which do not have a timezoe information.
Which version of plone.app.event with which version of Plone are you using?
It looks you're not using IEventBasic, so why are you hiding it's fields?

In general, IEventBasic's start and end date are required. If you don't provide them, there will be some errors. Instead of IEventBasic you can also define another behavior which implements plone.event.interfaces.IEvent like so:

# -*- coding: utf-8 -*-
from plone.app.event.base import default_timezone
from plone.app.event.dx.behaviors import IEventBasic
from plone.app.z3cform.widget import DatetimeFieldWidget
from plone.autoform import directives
from plone.autoform.interfaces import IFormFieldProvider
from zope import schema
from zope.interface import provider


@provider(IFormFieldProvider)
class IEventBasicNonRequired(IEventBasic):
    """ Basic event schema.
    """
    start = schema.Datetime(
        title=u'Event Starts'
        required=False,
        default=None
    )
    directives.widget(
        'start',
        DatetimeFieldWidget,
        default_timezone=default_timezone,
    )

    end = schema.Datetime(
        title=u'Event Ends'
        required=False,
        default=None
    )
    directives.widget(
        'end',
        DatetimeFieldWidget,
        default_timezone=default_timezone,
    )

Not sure if that helps...

1 Like

Thank you for the explanation of what could be causing the problem. So hiding fields can conflict with form controls if it handles hidden fields differently than nonhidden ones.

Thank you for your response. I forgot to mention that I was using IEventBasic as a behavior.
The reason I was using IEventBasic was because of the start and end fields, which zettwerk.fullcalendar can use and I can use. I have two fields e_start and e_duration. When its created or modified, the date portion of start and end are set to the value of e_start. The time components are set to 8:00 and e_start + e_duration.

Unfortunately when I tried your suggestion, I got an issue where it could not adapt

I'm going to rethink my approach to what I am actually trying to accomplish though.

Hidden fields are using form controls with type="hidden".

The potential problem is that if the cases for non-hidden and hidden fields use different logic one of those may be faulty - and as hidden fields are far less often used than non-hidden ones, a potential fault in the corresponding logic may go undetected for some time.