Fabian Fabian - 6 months ago 36
Python Question

django - FormSet: ingore forms contaning only initial values

I have a FormSet and each form contains one filed with initial value:

class IssueForm(forms.Form):

date_of_issue = forms.DateField(
initial=date.today().strftime("%d.%m.%Y"),
widget=forms.TextInput(attrs={
'placeholder': date.today().strftime("%d.%m.%Y"),
'class': 'form-control',
}),
localize=True,
required=True)


Now the user gets 10 extra forms displayed but maybe he/she just fills 5 of them. Now the field date_of_issue is required and so after submitting the formSet it'll be displayed again and marking those 5 rows not filled by the user.

I tried to add my own clean function for the field but I don't know if this is the way to go:

def clean_date_of_issue(self):
if len(self.cleaned_data) == 1 and 'date_of_issue' in self.cleaned_data:
self.cleaned_data = dict()
return None
return self.cleaned_data['date_of_issue']

Answer

Thx @håken-lid for pushing me into the code. I should have done it in the first place.

At the end I don't know what did the trick. I've overwritten most of the clean functions and check the errors at the levels of validation (read the docs. It helps!)

One thing is the show_hidden_initial. It seems to be necessary for the form to recognize that the initial value didn't change:

class IssueForm(forms.Form):
    # ...

    date_of_issue = forms.DateField(
            initial=date.today().strftime("%d.%m.%Y"),
            show_hidden_initial=True,
            widget=forms.TextInput(attrs={
                'placeholder': date.today().strftime("%d.%m.%Y"),
                'class': 'form-control, datepicker',
            }),
            localize=True,
            required=True)

Another approach was to overwrite the form clean function and remove the error (not a really nice solution):

class IssueForm(forms.Form):
    # ...

    def clean(self):
        cleaned_data = super(IssueForm, self).clean()

        # get all non default fields
        not_default_fields = [value for key, value in cleaned_data.items() if key not in ('date_of_issue', 'issuer')]

        if any(not_default_fields) is False and 'value' in self.errors:
            # remove the error if it's the only one
            self.errors.pop('value')

        return cleaned_data

I don't know why it didn't work like expected in the first place but now it does ...