user3747217
user3747217

Reputation: 21

Django Formset is_valid returns "True" though the field is empty when Form Class has only one field

Formset is_valid returns "True though the field is empty when Form Class has only one field.
I'd made this example using "python manage.py shell".
As you see, when the "ArticleForm" class has only title field, the formset's is_valid function return "True".
I saw somebody use the has_changed function because of this issue.
But I don't think that's good method to solve this problem.

from django import forms
from django.forms.formsets import formset_factory

class ArticleForm(forms.Form):
    title = forms.CharField()

ArticleFormSet = formset_factory(ArticleForm)
data = {
    'form-TOTAL_FORMS': '2',
    'form-INITIAL_FORMS': '0',
    'form-MAX_NUM_FORMS': '',
    'form-0-title': 'Test',
    'form-1-title': '',
}

formset = ArticleFormSet(data)
formset.is_valid()
#True - I think it has to be "False" because the "form-1-title' is empty
formset.errors
#[{}, {}]

class ArticleForm(forms.Form):
    title = forms.CharField()
    pub_date = forms.DateField()

ArticleFormSet = formset_factory(ArticleForm)
data = {
    'form-TOTAL_FORMS': '2',
    'form-INITIAL_FORMS': '0',
    'form-MAX_NUM_FORMS': '',
    'form-0-title': 'Test',
    'form-0-pub_date': '1904-06-16',
    'form-1-title': '',
    'form-1-pub_date': '1904-06-16',
}

formset = ArticleFormSet(data)
formset.is_valid()
#False - It's working. I think the reason is the pub_date field.
formset.errors
#[{}, {'title': [u'This field is required.']}]

Upvotes: 2

Views: 2344

Answers (1)

Karolis Ryselis
Karolis Ryselis

Reputation: 679

This is the default Django behaviour on empty forms. If Django notices that you have a completely empty form, it ignores it when running validation. In your second example your form is not empty because DateField has a value set.

You could see the advantage of this behaviour if you took a look at Django inlines. Imagine you have set

extra = 3

in your InlineAdmin. User fills in 2 inline forms and leaves out the third. The two forms are then validated properly and the empty one is ignored as one could expect.

In order to validate a one field form you could check your cleaned_data:

if formset.is_valid():
    is_really_valid = True
    for form in formset.forms:
        if not form.cleaned_data.has_key('title'):
            is_really_valid = False
            break

if this is a one field form, it does not really hurt much to check one field.

Upvotes: 5

Related Questions