Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Form DateInput with widget in update: loosing the initial value

I need a DateInput field in a ModelForm with the default HTML datepicker (I'm not using 3rd party libraries).

Since the DateInput is rendered with <input type = "text"> by default, the datepicker is missing (it comes for free with <input type = "date">)

I've found some examples explaining how to change the input type by handling widget parameters (below the code I've done so far)

The issue

I have the datepicker working correctly but in "update mode" when passing initial date value to the form (see view part), the date remains empty in the HTML.

I've tried to find the cause and it seems that the 'type': 'date' part in the widget customization is clearing the initial value is some way; in fact, removing it, the initial value date is displayed again, but I loose the datepicker of course.

In the view the date is passed with a valid value

I also found another similar unanswered question where the field was declared as

class DateInput(forms.DateInput):
    input_type = 'date'

date_effet = forms.DateField(widget=forms.DateInput(format='%d-%m-%Y'), label='Date effet')

the problem still remains

My code

model.py

class TimesheetItem(models.Model):

    date = models.DateField()
    description = models.CharField(max_length=100)
    # many other fields here

form.py

class TimesheetItemForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # init is used for other fields initialization and crispy forms


    class Meta:
        model = TimesheetItem
        fields = ['date', 'description']

        widgets = {
            'date': forms.DateInput(
                format=('%d/%m/%Y'),
                attrs={'class': 'form-control', 
                       'placeholder': 'Select a date',
                       'type': 'date'  # <--- IF I REMOVE THIS LINE, THE INITIAL VALUE IS DISPLAYED
                      }),
        }

 view.py

def edit(request, uuid):
    try:
        timesheet_entry_item = TimesheetItem.objects.get(uuid=uuid)

        if request.method == 'POST':
            form = TimesheetItemForm(
                data=request.POST,
                instance=timesheet_entry_item
            )

            if form.is_valid():
                pass # save the form
        else:
            form = TimesheetItemForm(initial={
                'date': timesheet_entry_item.date,  # <--- the date here has a valid value
                'description': timesheet_entry_item.description
            })
        return render(request, 'template.html', {'form': form})
    except ObjectDoesNotExist:
        raise Http404("error")

Thanks for any help

M.

like image 440
manuel_b Avatar asked Apr 07 '20 09:04

manuel_b


1 Answers

I managed to make it work. Following the cause of the issue, I hope it can be useful to others.

The HTML <input type='date'> element wants a date in the format YYYY-mm-dd; in fact an example of working HTML must be like this:

<input type="date" name="date" value="2020-03-31" 
class="form-control dateinput form-control" 
placeholder="Select a date" required="" id="id_date">

Since by default the form.DateInput produces the element <input type='text'>, it expects a date in the local format: let's say '31/03/2020'.

Forcing the 'type': 'date' and local format format=('%d/%m/%Y') or not passing a format at all, it ignores the value passed since the <input type='date'> wants format=('%Y-%m-%d')

At last the correct instruction was:

widgets = {
    'date': forms.DateInput(
        format=('%Y-%m-%d'),
        attrs={'class': 'form-control', 
               'placeholder': 'Select a date',
               'type': 'date'
              }),
}
like image 89
manuel_b Avatar answered Nov 06 '22 00:11

manuel_b