Reputation: 3433
I'm running into a date validation error with use of a django formset. I do not get the same validation error when I formset.is_valid()
. The problem I'm experiencing is that the form is_valid
check fails, only with the view and template use (not in the shell) specifically when using a date in the form of "March 20 2018" whereas it always passes with "2018-03-20".
Also I can verify the data is in the request.POST
but the invalid due_date
key is missing from self.cleaned_data when I look for it in the form's clean method. Perhaps that's normal given the invalid key but I would expect that to occur after the clean, not before, if at all. Feels like maybe its a django bug, I'm on django 2.0.2
Here's a summary of construction, its pretty vanilla:
# models.py
class Schedule(models.Model):
# ...
name = models.CharField(max_length=256)
status = models.CharField(max_length=16, default=choices.NOT_STARTED, choices=choices.SCHEDULE_STATUSES)
due_date = models.DateField(blank=True, null=True)
# ...
# forms.py
class ScheduleForm(forms.ModelForm):
class Meta:
model = models.Schedule
fields = ['name', 'user', 'status', 'due_date']
# views.py
def line_schedules_edit(request, line_slug):
line = get_object_or_404(models.Line, slug=line_slug)
queryset = line.schedules.all()
ScheduleFormSet = modelformset_factory(models.Schedule, form=forms.ScheduleForm)
if request.method == 'POST':
schedules_formset = ScheduleFormSet(request.POST)
if schedules_formset.is_valid():
schedules_formset.save()
return HttpResponseRedirect(reverse('products:line-schedules-edit',
kwargs={'line_slug': line_slug}))
else:
schedules_formset = ScheduleFormSet(queryset=queryset)
context = {
'line': line,
'formset': schedules_formset
}
return render(request, 'line-schedules-edit.html', context)
# template
{{ formset.management_form }}
{% csrf_token %}
{% for form in formset.forms %}
{% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field }}
{% endfor %}
{% endfor %}
With this structure I continually get an error of invalid date for due date when I use "March 3 2018" whereas if I provide a form input of "2018-03-18" in the browser, it works. Yet in a shell I'm able to verify that both date formats work:
In [35]: POST = {
'form-TOTAL_FORMS': '2',
'form-INITIAL_FORMS': '0',
'form-MAX_NUM_FORMS': '2',
'form-0-name': 'Test',
'form-0-status': 'Not started',
'form-0-due_date': '2018-03-20',
'form-1-name': 'Test',
'form-1-status': 'Not started',
'form-1-due_date': 'March 20, 2018'
}
In [36]: qdict = QueryDict('', mutable=True)
qdict.update(POST)
formset = ScheduleFormSet(qdict)
In [37]: formset.is_valid()
Out[37]: True
Why does the view and template fail the validation and why is the due_date
key missing in the form's clean method?
Upvotes: 0
Views: 316
Reputation: 3433
Turns out all I needed to do was to provide input formats to pre-process the format before its sent off to the model. It must have been built-in model validation failing since it cannot store it in the form of "March 2 2018".
Using input_formats
in the form, we can cast it to the desired format before the model processes it:
class ScheduleForm(forms.ModelForm):
class Meta:
model = models.Schedule
fields = ['name', 'user', 'status', 'due_date']
due_date = forms.DateField(widget=forms.DateInput(format='%d %B, %Y'),
input_formats=('%d %B, %Y',),
required=False)
Upvotes: 1