Opened 4 months ago

Last modified 2 weeks ago

#36468 assigned Bug

Popup stays blank after adding a related object when filter_horizontal is used

Reported by: Juan Rocha Owned by: Mark
Component: contrib.admin Version: 5.2
Severity: Normal Keywords: filter_horizontal; SelectBox; add_to_cache;
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Juan Rocha)

When using the "Add another" popup for a *ForeignKey field* in the Django admin and the same ModelAdmin has a ManyToManyField with *filter_horizontal*, the popup window does not close properly after adding the related object.

Instead, the popup remains open and white (blank), and the browser console throws the following error:

:8000/static/admin/js/SelectBox.js:60 Uncaught TypeError: Cannot read properties of undefined (reading 'push')
    at Object.add_to_cache (:8000/static/admin/js/SelectBox.js:60:33)
    at :8000/static/admin/j…ctLookups.js:115:31
    at NodeList.forEach (<anonymous>)
    at updateRelatedSelectsOptions (:8000/static/admin/j…ctLookups.js:103:24)
    at dismissAddRelatedObjectPopup (:8000/static/admin/j…ctLookups.js:133:17)
    at popup_response.js:12:16
add_to_cache @ :8000/static/admin/js/SelectBox.js:60
(anonymous) @ :8000/static/admin/j…bjectLookups.js:115
updateRelatedSelectsOptions @ :8000/static/admin/j…bjectLookups.js:103
dismissAddRelatedObjectPopup @ :8000/static/admin/j…bjectLookups.js:133
(anonymous) @ popup_response.js:12

This seems to be caused by this block in RelatedObjectLookups.js:

// Update SelectBox cache for related fields.
if (typeof SelectBox !== "undefined" && SelectBox.cache[currentSelect.id]) {
    SelectBox.add_to_cache(select.id, option);
    SelectBox.redisplay(select.id);
}

Steps to Reproduce

  1. Register a ModelAdmin with:
    • A ForeignKey field (with an "Add another" popup)
    • A ManyToManyField using filter_horizontal
  1. Click the "Add another" button next to the ForeignKey field
  2. In the popup, add the new object and submit
  3. The popup window stays open with a white screen
  4. Console shows a JavaScript error from SelectBox.js

Regression

This bug was introduced in commit:

https://github.com/django/django/commit/cd0479ff764272add5e0aba2afcf5649a241ca00

Expected Behavior

The popup should close normally and update the original select field with the new object, as it does when filter_horizontal is not present.

Workaround

Commenting out or removing the SelectBox.add_to_cache and SelectBox.redisplay lines in RelatedObjectLookups.js avoids the error and restores expected behavior.

Version

  • Django 5.2.X
  • Reproducible in the default admin interface

Change History (9)

comment:1 by Juan Rocha, 4 months ago

Description: modified (diff)

comment:2 by Natalia Bidart, 4 months ago

Resolution: worksforme
Status: newclosed

Hello Juan, thank you for your report. I'm not being able to reproduce: I'm using the models from #35331 (State and Transition) and after your step 3, the pop closes just fine.

Can you please share a test project or some tests so that we can replicate and validate the issue?

comment:3 by Mark, 4 weeks ago

Hello Natalia und Juan,

I stumbled accross the same problem, but the example Juan suggested did not work for me either.

In my case, the '+' popup needs to be triggered from within an inline form. A minimal example would look like this

Models:

from django.db import models


class Book(models.Model):
    title = models.CharField()


class Article(models.Model):
    title = models.CharField()
    books = models.ManyToManyField(Book, blank=True)


class Author(models.Model):
    name = models.CharField()


class Feature(models.Model):
    title = models.CharField()
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    article = models.ForeignKey(Article, on_delete=models.CASCADE)

Admin:

from django.contrib import admin

from .models import Article, Author, Book, Feature



class FeatureInline(admin.TabularInline):
    model = Feature


@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    inlines = [FeatureInline]
    filter_horizontal = ["books"]


@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    pass


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    pass


@admin.register(Feature)
class FeatureAdmin(admin.ModelAdmin):
    pass

Trying to add an author in the feature's inline (in the article's detail view) will produce the bug described by Juan.

A fix would be, to check, if the select input is managed by the SelectBox (~ it has been initialized) in RelatedObjectLookups.js (line 114)

if (window.SelectBox !== undefined && !SelectBox.cache[currentSelect.id] && SelectBox.cache[select.id]) {
...
}
Last edited 4 weeks ago by Mark (previous) (diff)

comment:4 by Mark, 2 weeks ago

Resolution: worksforme
Status: closednew
Triage Stage: UnreviewedAccepted

comment:5 by Mark, 2 weeks ago

Owner: set to Mark
Status: newassigned

comment:6 by Mark, 2 weeks ago

Has patch: set

comment:7 by Mark, 2 weeks ago

I've created a test and a fix at https://github.com/maqnius/django/tree/ticket_36468

./runtests.py --selenium=firefox -k test_popup_closes_with_filter_horizontal

comment:8 by Mark, 2 weeks ago

After investigating more, I figured out, that any select other than the triggered one, is affected by this. The inline is not necessary. Two foreign keys to the same model have the same effect.

from django.db import models


class Child(models.Model):
    name = models.CharField()


class Parent(models.Model):
    name = models.CharField()
    m2m = models.ManyToManyField(Child, blank=True)
    fk1 = models.ForeignKey(Child, on_delete=models.CASCADE, related_name="+")
    fk2 = models.ForeignKey(Child, on_delete=models.CASCADE, related_name="+")

I'll have a look, if this has any consequences for the bugfix.

Last edited 2 weeks ago by Mark (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top