djangovalidationerror

ValidationError not showing in template (although field validation errors are)


I am trying to raise ValidationError if a duplicate entry found in an inlineformset, just like in the docs: Custom formset validation I'm using a debugging tool and stepping through the code. It successfully reaches the line: raise ValidationError("Check Duplicate Entry"), and subsequently, in the view it takes the else statement instead proceeding with if formset.is_valid. I print(formset.non_form_errors) just as in the docs. However, the example in the docs returns a list at this stage with the error message inside it. In my case, I get <bound method BaseFormSet.non_form_errors of <django.forms.formsets.MyInlineFormSet object at 0x7fcc22e89610>> The template renders with the form data but the validation error does not appear to say what is wrong. I'm missing something for sure. Any help appreciated.

class MyInlineFormSet(BaseInlineFormSet):

    def __init__(self, *args, **kwargs):
        super(MyInlineFormSet, self).__init__(*args, **kwargs)
        for form in self.forms:
            form.empty_permitted = False

    def clean(self):
        if any(self.errors):
            return
        mylist = []
        for form in self.forms:
            myfield_data = form.cleaned_data.get("myfield")
            if myfield_data in mylist:
                raise ValidationError("Check Duplicate Entry")
            mylist.append(myfield_data)

My tempate just has this:

{% block content %}
<section class="container-fluid">
    {% crispy form %}
</section>
{% endblock content %}

Side Note: Any field validation errors against specific fields do show up. But there I am writing the errors like so: self._errors["fieldname"] = self.error_class(["Error in field, please double check"]) Not sure why raise ValidationError is not working for the formset


Solution

  • SOLVED! My formset is a crsipy form within a crispy form. The overall form is rendered in the template linked to the view. But I should have mentioned, I have a separate template containing the markup for the formset.

       <div class="row justify-content-center">
          <div class="col-7">
           {{ formset.management_form | crispy }}
            {% for form in formset.forms %}
                <h3>Form {{forloop.counter}}</h3>
                {% crispy form %}
            {% endfor %}
           </div>
           <br>
       </div>
    

    So I just needed to add {{ formset.non_form_errors }} below formset.management_form.