Hi, 

Yesterday and today I implemented something and I had a surprise. I'm
explaining here with questions at the end but also in case that I might
save some time to someone working with forms (if someone is going to try
the same approach that I did and it doesn't work).

What I want to do: the user fills in a form (with Django forms using
django-crispy-form). If there is a validation error in a specific field
I need to show a new Field (a checkbox) in order to get confirmation
before the final submission.

Very important: this form is in an InlineFormSet (via inlineformset_factory)

My first reaction: in MyForm.__init__(self) I did something along the lines 
(pseudocode) of:
"""
    if 'amount' in self.errors:
        self.fields['allow_error'] = forms.BooleanField()
        divs.append('allow_error')
"""

This worked... but it has one problem that some people might have
already spotted! The deletion was not working. kwargs['data'] contained
the 'DELETE' key correctly (with the prefix, etc.). But it was not
available in self.clean_fields when it was trying to be used by Django
in order to decide if the form was going to be deleted.

After some investigation:
self.errors is a property and calls BaseForm.errors which does:
"""
        if self._errors is None:
            self.full_clean()
        return self._errors
"""
(https://github.com/django/django/blob/master/django/forms/forms.py#L169)


My form is created in BaseFormSet._construct_form method. This does (at the 
very end):
"""
        form = self.form(**defaults)
        self.add_fields(form, i)
"""
(https://github.com/django/django/blob/master/django/forms/formsets.py#L175)

The "add_fields" method adds the "DELETE" in self.fields:
(https://github.com/django/django/blob/master/django/forms/formsets.py#L390)

It needs to be in self.fields when self.clean_data is populated or it is 
ignored.

Since in the MyForm.__init__ method I called self.errors and the result
is cached/optimized: 'DELETE' is never added in self.clean_fields (it's
not in self.fields when I called self.errors that triggers the
validation, full_clean, etc; and when it's added in self.fields it's too
late) and then the form never triggers the deletion.

I have some questions:
a) Does it say somewhere in the documents to avoid calling self.errors
from the __init__? I might have missed it. I had some similar problem
using the debugger (via self.errors or self.is_valid perhaps, etc.).

b) I currently now read data from self.data and get the number that I
need and I apply the same logic as the "clean" to decide if I need to
show the checkbox or not. I wonder if there is some other way to
approach this issue that is a bit cleaner (avoiding self.data, self
contained in the form logic, etc.). Do you use any other approach?

c) Actually, should Django tried to prevent my error somehow? :-)

Thanks very much!

-- 
Carles Pina i Estany

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/20200618141534.GA30379%40pina.cat.

Reply via email to