Skip to content

Instantly share code, notes, and snippets.

@andytwoods
Last active March 21, 2023 21:09
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andytwoods/76f18f5ddeba9192d51dccc922086e43 to your computer and use it in GitHub Desktop.
Save andytwoods/76f18f5ddeba9192d51dccc922086e43 to your computer and use it in GitHub Desktop.
Django splitDateTime widget, no JS, using modern HTML for time and date selectors
from datetime import datetime
from django.utils.timezone import make_aware
from django.forms import TextInput, MultiWidget, DateTimeField
# nightmare discussion here https://stackoverflow.com/questions/38601/using-django-time-date-widgets-in-custom-form
class MinimalSplitDateTimeMultiWidget(MultiWidget):
def __init__(self, widgets=None, attrs=None):
if widgets is None:
if attrs is None:
attrs = {}
date_attrs = attrs.copy()
time_attrs = attrs.copy()
date_attrs['type'] = 'date'
time_attrs['type'] = 'time'
widgets = [
TextInput(attrs=date_attrs),
TextInput(attrs=time_attrs),
]
super().__init__(widgets, attrs)
# nabbing from https://docs.djangoproject.com/en/3.1/ref/forms/widgets/#django.forms.MultiWidget.decompress
def decompress(self, value):
if value:
return [value.date(), value.strftime('%H:%M')]
return [None, None]
def value_from_datadict(self, data, files, name):
date_str, time_str = super().value_from_datadict(data, files, name)
# DateField expects a single string that it can parse into a date.
if date_str == time_str == '':
return None
if time_str == '':
time_str = '00:00'
my_datetime = datetime.strptime(date_str + ' ' + time_str, "%Y-%m-%d %H:%M")
# making timezone aware
return make_aware(my_datetime)
@rrr3try
Copy link

rrr3try commented Jul 20, 2021

And it doesn't work in desktop Firefox... 8 years long bug... Thanks anyway!

@DrPeeps
Copy link

DrPeeps commented Mar 21, 2023

In Firefox 111.0 the widget always fails validation and says "Enter a list of values." Why should it fail in Firefox specifically?

@rrr3try
Copy link

rrr3try commented Mar 21, 2023

In Firefox 111.0 the widget always fails validation and says "Enter a list of values." Why should it fail in Firefox specifically?

https://stackoverflow.com/a/68451933/11354529

@DrPeeps
Copy link

DrPeeps commented Mar 21, 2023

Thanks, I did see the Django admin solution ... but I still question why this shouldn't work in Firefox - both 'date' and 'time' input types are supported by the browser.

Actually, they are working fine in Firefox. I think my validation failure may be due to me using this solution incorrectly. Any tips as to how the above class should be used with a DateTime field in a Form? I am simply using is as the widget for a SplitDateTimeField, which I suspect doesn't work:

class SplitDateTimeField(SplitDateTimeField):
    widget = MinimalSplitDateTimeMultiWidget

The issue appears to be that my field never gets properly populated with the date/time data in the POST. "fieldname_0" and "fieldname_1" are created and populated with the correct date/time data, but are never passed on to "fieldname" itself ... so the form fails validation because the field is still considered empty.

@DrPeeps
Copy link

DrPeeps commented Mar 21, 2023

I've replaced this solution with the shorter one posted by @spookylukey and it seems to work fine. So I don't think it has anything to do with Firefox.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment