0

I got some strange behavior with formset validation for model form formset. I'am using Django 1.5, python 2.7 Here is code what i used.

Model class:

class WorkDone(models.Model):
    task = models.ForeignKey(Task)
    type_of_work = models.ForeignKey("pricelist.TypeOfWork")

Form class:

class WorkDoneForm(forms.ModelForm):

    class Meta:
        model = WorkDone
        exclude = ("task",)

    def __init__(self, *args, **kwargs):
        super(WorkDoneForm, self).__init__(*args, **kwargs)
        self.fields["type_of_work"].widget = forms.HiddenInput()

Formset class generation:

WorkDoneFormSet = formset_factory(WorkDoneForm, can_delete=True)

Formset creation in get_context_data function of view:

context["work_done_formset"] = context.get("work_done_formset", WorkDoneFormSet(prefix='work_done'))

So, i submit form with one WorkDone form in formset without any entered data(for typeOfWork of course) and here POST data from POST request:

QueryDict: {u'_save': [u''],  
    u'work_done-0-type_of_work': [u''],  
    u'work_done-INITIAL_FORMS': [u'0'], 
    u'work_done-TOTAL_FORMS': [u'1'], 
    u'csrfmiddlewaretoken': [u'nFkTCyx3413yrFE9XpNQDGdNlzPAHwyI'], 
    u'work_done-MAX_NUM_FORMS': [u'1000']}

And output from this code bellow in view:

work_done_formset = WorkDoneFormSet(request.POST, prefix="work_done")
print work_done_formset.is_valid(), work_done_formset.cleaned_data
for form in work_done_formset:
    print form.is_valid(), form.cleaned_data

>> True [{}]
>> True {}

Why validation is true and why there is no error for missing TypeOfWork fields in form? Thank you.

Andrey Baryshnikov
  • 781
  • 2
  • 12
  • 22
  • This is because nothing has changed in the formset. The validation per form triggers only when something has changed in the individual form of the formset – karthikr Sep 13 '13 at 17:21
  • So, i need to set the default value for form field for validation trigger? Or, maybe, initial form count > 0? – Andrey Baryshnikov Sep 13 '13 at 17:24
  • 1
    well. even that would not work - because django formsets have a property called `formset.has_changed()` which would not change. If you have only 1 form, why not just go with a single form ? – karthikr Sep 13 '13 at 17:27
  • No, there can be many forms, because they can be added via js on user-side. – Andrey Baryshnikov Sep 13 '13 at 17:28
  • 1
    Oh.. One thing you can do is, override the `def clean` method of the and ensure atleast one form is filled. – karthikr Sep 13 '13 at 17:29
  • So, there is no way without overriding BaseFormset class? Or, i can use default value in such fields, so field will not be null by default, or user will change it value so validation will trigger? – Andrey Baryshnikov Sep 13 '13 at 17:32
  • Well. Thats the only way I can think of. Lets wait and see if someone else has a better idea. I would be keen to know too :) – karthikr Sep 13 '13 at 17:42
  • 2
    One more alternative: http://stackoverflow.com/a/4951032/1628832 – karthikr Sep 13 '13 at 17:58
  • Setting `empty_permitted` on one or all of my forms after instantiating the formset, as demonstrated in that answer, is how I've solved this in the past. – Peter DeGlopper Sep 13 '13 at 18:38

0 Answers0