django-nested-inline icon indicating copy to clipboard operation
django-nested-inline copied to clipboard

Error in nested inline not bubbling up

Open leibowitz opened this issue 3 years ago • 3 comments

I am using django-nested-inline with a model defined like this:

Person
└─ House
    └─Room

My Admin is defined in this way:

from nested_inline.admin import NestedStackedInline, NestedModelAdmin

class RoomInlineStacked(NestedStackedInline):
    ...

class HouseInline(NestedStackedInline):
    inlines = [RoomInlineStacked]

class PersonAdmin(NestedModelAdmin):
    inlines = [HouseInline]

The form displays correctly, and works fine, until there is an error in the RoomInlineStacked. In which case, the error is only displayed within the inline formset, but not at the top level (where errors are normally shown)

Errors within HouseInline are reported correctly at the top of the page. I'm expecting this to happen for the RoomInlineStacked as well. aka I'm expecting to see this (which doesn't happen at the moment): Screenshot 2021-06-18 at 11 19 10

I am trying to understand what's missing within AdminErrorList in https://github.com/s-block/django-nested-inline/blob/master/nested_inline/admin.py#L264 but I'm struggling to navigate the structure of formsets/forms/inlines and other attributes to find the error from the underlying NestedStackedInline and send it back up to the NestedModelAdmin.

Any pointers appreciated

leibowitz avatar Jun 18 '21 10:06 leibowitz

I am facing the same issue.

fpoulain avatar Feb 10 '22 16:02 fpoulain

The problem is that helpers.AdminErrorList isn't builded to catch recursively errors (at arbitrary level) and it is not called with recursive formsets.

Since all_valid_with_nesting is walking recursively formsets, I suggest to backstep the error at this step.

fpoulain avatar Feb 10 '22 17:02 fpoulain

My fix occurs in some private code but I simply redefined def all_valid_with_nesting in a subclass of NestedModelAdmin and added

             for form in formset:
                 if hasattr(form, 'nested_formsets'):
+                    if not self.all_valid_with_nesting(form.nested_formsets):
+                        # backstep error
+                        form.errors[None] = [
+                            f.errors + f.non_form_errors()
+                            for f in form.nested_formsets
+                        ]
                        return False

fpoulain avatar Feb 10 '22 17:02 fpoulain