1
0
mirror of https://github.com/django/django.git synced 2025-09-10 11:09:12 +00:00

Fixed #34624 -- Removed change, delete, and view buttons for non-Select widgets in RelatedFieldWidgetWrapper.

Signed-off-by: SaJH <wogur981208@gmail.com>
This commit is contained in:
SaJH 2025-08-27 23:34:04 +09:00 committed by Sarah Boyce
parent 550822bcee
commit 0be1c4575b
2 changed files with 23 additions and 5 deletions

View File

@ -10,6 +10,7 @@ from django.conf import settings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import URLValidator from django.core.validators import URLValidator
from django.db.models import CASCADE, UUIDField from django.db.models import CASCADE, UUIDField
from django.forms.widgets import Select
from django.urls import reverse from django.urls import reverse
from django.urls.exceptions import NoReverseMatch from django.urls.exceptions import NoReverseMatch
from django.utils.html import smart_urlquote from django.utils.html import smart_urlquote
@ -284,16 +285,18 @@ class RelatedFieldWidgetWrapper(forms.Widget):
if can_add_related is None: if can_add_related is None:
can_add_related = admin_site.is_registered(rel.model) can_add_related = admin_site.is_registered(rel.model)
self.can_add_related = can_add_related self.can_add_related = can_add_related
# XXX: The UX does not support multiple selected values.
multiple = getattr(widget, "allow_multiple_selected", False)
if not isinstance(widget, AutocompleteMixin): if not isinstance(widget, AutocompleteMixin):
self.attrs["data-context"] = "available-source" self.attrs["data-context"] = "available-source"
self.can_change_related = not multiple and can_change_related # Only single-select Select widgets are supported.
supported = not getattr(
widget, "allow_multiple_selected", False
) and isinstance(widget, Select)
self.can_change_related = supported and can_change_related
# XXX: The deletion UX can be confusing when dealing with cascading # XXX: The deletion UX can be confusing when dealing with cascading
# deletion. # deletion.
cascade = getattr(rel, "on_delete", None) is CASCADE cascade = getattr(rel, "on_delete", None) is CASCADE
self.can_delete_related = not multiple and not cascade and can_delete_related self.can_delete_related = supported and not cascade and can_delete_related
self.can_view_related = not multiple and can_view_related self.can_view_related = supported and can_view_related
# To check if the related object is registered with this AdminSite. # To check if the related object is registered with this AdminSite.
self.admin_site = admin_site self.admin_site = admin_site
self.use_fieldset = True self.use_fieldset = True

View File

@ -978,6 +978,21 @@ class RelatedFieldWidgetWrapperTests(SimpleTestCase):
""" """
self.assertHTMLEqual(output, expected) self.assertHTMLEqual(output, expected)
def test_non_select_widget_cant_change_delete_related(self):
main_band = Event._meta.get_field("main_band")
widget = widgets.AdminRadioSelect()
wrapper = widgets.RelatedFieldWidgetWrapper(
widget,
main_band,
widget_admin_site,
can_add_related=True,
can_change_related=True,
can_delete_related=True,
)
self.assertTrue(wrapper.can_add_related)
self.assertFalse(wrapper.can_change_related)
self.assertFalse(wrapper.can_delete_related)
@override_settings(ROOT_URLCONF="admin_widgets.urls") @override_settings(ROOT_URLCONF="admin_widgets.urls")
class AdminWidgetSeleniumTestCase(AdminSeleniumTestCase): class AdminWidgetSeleniumTestCase(AdminSeleniumTestCase):