Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with inline on junction model: The inline value did not match the parent instance. #261

Open
ppo opened this issue Jan 20, 2021 · 0 comments

Comments

@ppo
Copy link

ppo commented Jan 20, 2021

SOLVED while writing this so, let's keep it for reference…

TL;DR: As mentioned in the documentation:

my_order is the first field in the ordering tuple of the model’s Meta class.

The doc could be more explicit, for example:

my_order MUST ABSOLUTELY be the first field in the ordering tuple. It's retrieved first from the ModelAdmin, otherwise from the Model.Meta class.

FEATURE REQUEST: (already requested in #155, #198)
Please allow to specify the order field in the Model.
It makes sense to sort first on another field in junction models. Especially as that ordering is used elsewhere.


In inlines, the drag&drop works but there's just a global error message Please correct the errors below. but no specific errors in the form/formset… so it seems the error is on a missing or well hidden field.

Tracing down the problem, there's an error on a field in the inline's formset: The inline value did not match the parent instance.

Investigating in the HTML, apparently there's no order value and it's the album_id that is changed with the new sorting order (which explains the error message).

Investigating in the JS, it looks for a default_order_field.

Investigating in the admin.py, there's a _get_default_ordering function that finds it from the first item in the model_admin.ordering or model._meta.ordering… OK 🤬😕🙄


"Conceptual" code…

class Media(Model): …

class Album(Model):
    medias = models.ManyToManyField(Media, through="AlbumMedias")

class AlbumMedias(Model):
    album, media, order
    class Meta:
        ordering = ["album", "order"]  # /!\ WRONG! `order` must be the first item.

class AlbumAdminInline(SortableAdminInlineMixin, TabularInline):
    model = Album.medias.through
    # Try 1: No fields defined
    # Try 2: fields = ["media"]
    # Try 3: fields = ["order", "media"]

class AlbumAdmin(SortableAdminMixin, ModelAdmin):
    inlines = [AlbumAdminInline]

    def save_form(self, request, form, change):
        obj = super().save_form(request, form, change)
        breakpoint()
        return obj

Debug:

> //my-app/admin.py(131)save_form()
-> return obj
(Pdb) n
--Return--
> //my-app/admin.py(131)save_form()-><Album: Foo>
-> return obj
(Pdb) n
> //django/contrib/admin/options.py(1578)_changeform_view()
-> formsets, inline_instances = self._create_formsets(request, new_object, change=not add)
(Pdb) n
> //django/contrib/admin/options.py(1579)_changeform_view()
-> if all_valid(formsets) and form_validated:
(Pdb) formsets[0].errors
[{'album': ['The inline value did not match the parent instance.']}, …(same for all inline rows, of course)…]

Admin page before drag&drop:

<td class="original"><input type="hidden" name="album_medias-0-id" value="123" id="id_album_medias-0-id">
  <input type="hidden" name="album_medias-0-album" value="987" id="id_album_medias-0-album">
</td>
<td class="original"><input type="hidden" name="album_medias-1-id" value="124" id="id_album_medias-1-id">
  <input type="hidden" name="album_medias-1-album" value="987" id="id_album_medias-1-album">
</td>

Admin page after drag&drop:

<td class="original"><input type="hidden" name="album_medias-1-id" value="124" id="id_album_medias-1-id">
  <input type="hidden" name="album_medias-1-album" value="1" id="id_album_medias-1-album">
</td>
<td class="original"><input type="hidden" name="album_medias-0-id" value="123" id="id_album_medias-0-id">
  <input type="hidden" name="album_medias-0-album" value="2" id="id_album_medias-0-album">
</td>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant