I had the following code working in Django 1.5:
if formset.is_valid():
formset.save()
The forms inside the formset are performing a check inside clean() to make sure that certain required fields are entered (only known at runtime). This means that although a user might not enter any values the validation would still run and ask for data entry if required.
With Django 1.6 this behaviour does not apply anymore. If there was no change then the form's clean() method does not get called anymore when calling formset.is_valid().
I could not find anything in the changelogs that would explain this new behvaiour. Is there a flag on formset.is_valid() to force the validation even if no changes were made?
It seems as if the validation was skipped since the formset changed the form's edit_permitted attribute.
The following change fixed the issue I had:
# Was required to disable shortcut for validation when
# no data was entered
for form in formset:
form.empty_permitted = False
Related
I have a form with a bunch of fields but I also pass in values like the current page they submitted the form from and the user, which are hidden fields.
So from what I understand is_valid() will fail because of that. So do I need to run is_valid()?
For example, one of my forms has the line:
self.fields['user'].widget = forms.HiddenInput()
Yes, the form will be validated for all fields - depending upon required/non-required or default etc - for hidden fields as well with respect to provided data.
If you want to save or use the submitted data, you should validate the form using is_valid().
Django says "Note that if the form hasn’t been validated, calling save() will do so by checking form.errors. A ValueError will be raised if the data in the form doesn’t validate – i.e., if form.errors evaluates to True."
What I am not able to clear out is
Will the validation be run when I call the save on the ModelForm?
And if I have validated the form data using form.is_valid() method than will the save() method do the validation again.(I am asking this as some validation requires I do a database query for Foreign Key validation as it has some restriction)
I am asking this question as if the first one is true than I think it would be a good idea to not to validation at all and rather just call the save method, letting it call the validation method and just catching it.
First question - yes. As the docs say, calling save() accesses form.errors, which triggers validation if the form has not yet been validated.
Second question - no, the validation will not be run again. Once the form has been validated, whether by calling is_valid() or by calling .save(), form.errors is populated and can be read from without re-running validation.
With either approach, validation will be run exactly once.
I have a formset that generates two forms that have different initial values. When the user submits the form, they're only going to fill out one of them, not both. These initial values get populated in the view, which (I think) means FormSet can't figure out if they've changed or not, so default validation fails. But really, all I care about is if one of them is valid. I'd like to take that valid form and process it. What's the best way to go about this?
Not only formset.is_valid() exists, but also
for form in formset.forms:
if form.is_valid():
..
should work.
Is it possible to add form errors (not a field specific errors) to a form that is already validated (form.is_valid() is already called and the result is True)?
I have additional validation logic (with database requests) which I prefer to execute after standard form validation is passed, but it will be better to associate new errors with form
Or maybe I have to call this additional validation within clear() form function?
Try to check it in the clean method of the form after all, but check existing errors before.
Like that..
clean(self):
...
...
if not self._errors:
# your extra check
If this is validation based on database requests, then it shound as model validation.
I have a from based on ModelForm and use formset_factory to create a formset based on two dictionaries. There is also one extra form.
In my view, I use the formset JS plugin and I delete the two forms with data. When I POST the remaining empty extra form, it fails validation because of a required field.
I don't understand why that form is being validated. Its changed_data list is empty. It is returned with empty_permitted = False (and I'd like to know why that is), but even after I change it to True in the debugger, it is validated.
So what is triggering validation and how can I modify it?
I would also be interested to know where data like the initial data is stored. Is that somewhere in my view where I am not seeing it?
The template management form has a counter called INITIAL_FORMS. The formset plugin for adding and deleting forms does not distinguish between initially populated forms and forms it adds. When a form is deleted, if it was initially populated, then INITIAL_FORMS should be decremented.
This can be implemented by including a template variable which flags forms which are initially populated. In the removed function of the formset plugin, if one of these flagged forms is being deleted, then decrement INITIAL_FORMS.