5

I'm using the HTML5 datetime-local input type to try and get some datetime data into my database.

The ModelForm class Meta: looks like the following:

class Meta:
    model = ScheduleEntry
    fields = ['calendar', 'title', 'start', 'end', 'assets', 'users']

    widgets = {
        'calendar': forms.Select(attrs={
            'class': 'fom-control chosen-select'
        }),
        'title': forms.TextInput(attrs={
            'class': 'form-control'
        }),
        'start': forms.DateTimeInput(attrs={
            'type':'datetime-local',
            'class':'form-control'
        }, format='%Y-%m-%dT%H:%M'),
        'end': forms.DateTimeInput(attrs={
            'type': 'datetime-local',
            'class': 'form-control'
        }, format='%Y-%m-%dT%H:%M'),
        'assets': forms.SelectMultiple(attrs={
            'class': 'form-control chosen-select'
        }),
        'users': forms.SelectMultiple(attrs={
            'class': 'form-control chosen-select',
        })

    }

I keep failing on form validation and it's causing me to pull my hair out.This is the documentation page that shows it should work, but it looks like I'm missing something?

EDIT FOR CLARIFICATION:

The error message is for both start and end and it's Enter a valid date/time

James Martinez
  • 191
  • 2
  • 11
robotHamster
  • 609
  • 1
  • 7
  • 24

3 Answers3

11

The misconception:

To quote the docs:

Widgets should not be confused with the form fields. Form fields deal with the logic of input validation and are used directly in templates. Widgets deal with rendering of HTML form input elements on the web page and extraction of raw submitted data.

Widgets have no influence on validation. You gave your widgets a format argument, but that does not mean the form field validation will use it - it only sets the initial format the widget's content is rendered with:

format: The format in which this field’s initial value will be displayed.


The solutions

Two options:

  • provide the form field (forms.DateTimeField) with the datetime format you would like to use by passing a input_formats argument

    class MyIdealDateForm(forms.ModelForm):
        start = forms.DateTimeField(
            input_formats = ['%Y-%m-%dT%H:%M'],
            widget = forms.DateTimeInput(
                attrs={
                    'type': 'datetime-local',
                    'class': 'form-control'},
                format='%Y-%m-%dT%H:%M')
        )
    

    This needs to be done for every form field (and probably by extension even their widgets). What you are doing here is effectively overwriting the settings (see the next point).

  • Add your datetime format to the settings as the first item. This will apply globally to all formfields and widgets that use that setting.

CoffeeBasedLifeform
  • 2,296
  • 12
  • 27
  • Thank you **very much!** for the clarification. Before I accept this as the answer: am I correct to assume that the above solution _does_ imply that I will have to handle saving in the dates in my view code so `form.save()` wouldn't completely take care of it (which IMHO is the biggest advantage of using a `ModelForm`) ? – robotHamster Nov 08 '18 at 07:13
  • 1
    No, if you provide the correct format in either fashion, the field's `clean` method will spew out the `datetime.datetime` instance that the form needs to save properly. I have made some edits to the answer, including some very important details: 1) it's `input_formats` not `input_format` 2) `input_formats` needs to be an iterable (or it will, rather confusingly, raise a `ValidationError`). I strongly suggest the settings approach. – CoffeeBasedLifeform Nov 08 '18 at 16:46
0

you just have a typo. Make it 'form' instead of 'fom' in class value.

'calendar': forms.Select(attrs={ 'class': 'fom-control chosen-select' }),

dp2050
  • 332
  • 3
  • 8
0

Maybe you need to import datetime to ensure it's a valid date/time format for python, here you can see an aproach.

ccmorataya
  • 69
  • 2
  • 9