Saturday, January 22, 2022

Specifying the value format for a DateTimeInput using type=datetime-local, especially when using inline formsets

I think I found a fix to a bug that I don't know was affecting anyone other than me.


TL;DR: For a DateTimeInput widget where type='datetime-local', specify the default format to include the T in the middle of the date-time string:

widgets={ 'when':forms.DateTimeInput( format='%Y-%m-%dT%H:%M:%S', attrs={'type':'datetime-local'} ), ... }

This was driving me crazy!

I had a model inline formset using a form:

forms.py:

TicketNoteFormset = inlineformset_factory(Ticket, TicketNote, form=TicketNoteForm, extra=10)

The specified form (TicketNoteForm) had a widget specified for a DateTime field:

forms.py:

class TicketTicketNoteForm(forms.ModelForm): class Meta: model = TicketNote fields = [ 'when', 'text', ] widgets={ 'when':forms.DateInput(attrs={'type':'date'}), 'text':forms.TextInput(attrs={'class':'len100'}) }

My mistake was using DateInput for the field 'when', which was a DateTimeField, not a DateField
models.py:

class TicketNote(models.Model): when = models.DateTimeField( 'when', default=datetime.now, help_text='The date that the note was submitted' )

In the HTML forms, the initial value, as expected, was a date-time value but the value attribute of the field was a date value without the time

<input type="date" name="ticketnote_set-0-when" value="2022-01-22 06:52:09" id="id_ticketnote_set-0-when"> <input type="hidden" name="initial-ticketnote_set-0-when" value="2022-01-22 06:52:09" id="initial-ticketnote_set-0-id_ticketnote_set-0-when">

The difference between initial and non-initial caused a record to be created even if the form was blank

But it was still broken after I fixed it

Leaving out the widget declaration works, but then I just get a plain text field and I want to take advantage of the browser's popup calendar

I thought I had the problem fixed by specifying the widget as

forms.py:

DateTimeInput(attrs={'type':'datetime-local'}),

but that's still giving me some problems. It worked fine in Firefox, but Chrome ignored the value attribute. So in Chrome

<input type="datetime-local" value="2022-01-01 08:01:00">

displays a blank datetime input and submits an empty string if not updated

I'll update if I find a good solution.

Update: This works in Firefox and Chrome:
forms.py:

widgets={ 'when':forms.DateTimeInput( format='%Y-%m-%dT%H:%M:%S', attrs={'type':'datetime-local'} ), ... }

What Chrome was rejecting was having the value specified without the T between the date portion and the time portion. Django was producing the value without the T. By adding the format argument, I was able to make Django produce a default value that Chrome accepts.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/d4b3bb1f-d296-4928-9e69-a0774acc5886n%40googlegroups.com.

No comments:

Post a Comment