Widget `AdminSplitDateTime` causing exception on `list` object

I’m upgrading a python project from Python 2.7 + Django 1.8 to Python 3.7 + Django 3.1. The application contains a form using widgets.AdminSplitDateTime to create a GUI effect of splitting the date and time parts. This widget makes a field of DateTime into a list of two objects, and its default value is [None, None].

On the older version with Django v1.8.13, function DateTimeField.to_python contains a logic path to handle it as if isinstance(value, list): ... in the source code below. Notice that there was already a warning about SplitDateTimeWidget deprecated.

In current Django version, this logic path is removed; so the program gets an exception saying 'list' object has no attribute 'strip' when calling result = parse_datetime(value.strip())

In another post, I found a workaround to remove widget AdminSplitDateTime. But if want to keep the GUI design of spiting date and time, is there anything I can do?

Any hint will be highly appreciated.

Details:

1. The form in my application source code:

class ProductAdminForm(BaseDynamicEntityForm):
    ...
    def _build_dynamic_fields(self):
        ...
        # this line is the primary reason for override, additional filter on the fields by business
        for attribute in self.entity.get_all_attributes()\
            .filter(producttemplateattribute__product_template=product_template):
            ...
            elif datatype == attribute.TYPE_DATE:
                defaults.update({'widget': AdminSplitDateTime})
            ...

2. The source code of Django 1.8:

class DateTimeField(BaseTemporalField):
    ...
    def to_python(self, value):
        """
        Validates that the input can be converted to a datetime. Returns a
        Python datetime.datetime object.
        """
        if value in self.empty_values:
            return None
        if isinstance(value, datetime.datetime):
            return from_current_timezone(value)
        if isinstance(value, datetime.date):
            result = datetime.datetime(value.year, value.month, value.day)
            return from_current_timezone(result)
        if isinstance(value, list):
            # Input comes from a SplitDateTimeWidget, for example. So, it's two
            # components: date and time.
            warnings.warn(
                'Using SplitDateTimeWidget with DateTimeField is deprecated. '
                'Use SplitDateTimeField instead.',
                RemovedInDjango19Warning, stacklevel=2)
            if len(value) != 2:
                raise ValidationError(self.error_messages['invalid'], code='invalid')
            if value[0] in self.empty_values and value[1] in self.empty_values:
                return None
            value = '%s %s' % tuple(value)
        result = super(DateTimeField, self).to_python(value)
        return from_current_timezone(result)

You might be looking for the SplitDateTimeField and the corresponding widget SplitDateTimeWidget?

1 Like