views:

159

answers:

2

How to make all forms in django formset required? I tried to validate presence of all fields in cleaned_data overriding formset's clean() method but it just fails silently without any error displayed.

Thanks!

Source code:

class BaseScheduleForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(BaseScheduleForm, self).__init__(*args, **kwargs)
        self.fields['day'].widget = forms.HiddenInput()
        self.fields['user'].widget = forms.HiddenInput()

    class Meta:
        model = Schedule

    def clean_end_time(self):
        start_time = self.cleaned_data.get('start_time')
        end_time = self.cleaned_data['end_time']

        if start_time and end_time:
            if end_time <= start_time:
                raise forms.ValidationError("End time must be later that start time.")
        return end_time

class BaseScheduleFormset(forms.models.BaseModelFormSet):

    def __init__(self, *args, **kwargs):
        super(BaseScheduleFormset, self).__init__(*args, **kwargs)
        for number, weekday in enumerate(WEEKDAYS):
            self.forms[number].day_name = weekday[1]

    def clean(self):
        raise forms.ValidationError('You must specify schedule for the whole week')

ScheduleFormset = forms.models.modelformset_factory(Schedule, extra=7, max_num=7,
    form=BaseScheduleForm, formset=BaseScheduleFormset)

There are 7 forms each for one day and all of them must be filled to be valid. In example above I just tried to raise error in clean. is_valid() became False, but no errors were displayed.

A: 

It's a bit hard to understand where the errors are not being displayed.

If is_valid is False, then good, the validation it self is working. Then the next place to look is for the templating layer. How are you checking for errors? {{form.errors}} or {{somefield.errors}}.

The way the clean methods are setup here, their errors will not be associated with any fields, but should go in the all erros slot.

Cheers

Arthur Debert
formset.errors is empty though formset.is_valid() is false. Looks like a bug for me.
Dmitry Gladkov
A: 

I had this same problem and figured out where these errors were stored by checking the source. When you override the clean method of a formset and raise a validation error the errors are stored in the non_form_errors property.

So in your template you would need to add the following assuming the template variable for formset is named 'formset':

{{ formset.non_form_errors }}
AJ