From 3d4d0a25b299a97314582156a0d63d939662d310 Mon Sep 17 00:00:00 2001 From: Javier Matos Odut Date: Wed, 31 Oct 2018 15:16:17 +0100 Subject: [PATCH] Fixed #29901 -- Allowed overriding an autocomplete/raw_id_fields/radio_fields widget with ModelAdmin.get_formset(). --- django/contrib/admin/options.py | 19 ++++++++++--------- tests/modeladmin/tests.py | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 43a90b302c5..241d22e82ae 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -224,15 +224,16 @@ class BaseModelAdmin(metaclass=forms.MediaDefiningClass): """ db = kwargs.get('using') - if db_field.name in self.get_autocomplete_fields(request): - kwargs['widget'] = AutocompleteSelect(db_field.remote_field, self.admin_site, using=db) - elif db_field.name in self.raw_id_fields: - kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.remote_field, self.admin_site, using=db) - elif db_field.name in self.radio_fields: - kwargs['widget'] = widgets.AdminRadioSelect(attrs={ - 'class': get_ul_class(self.radio_fields[db_field.name]), - }) - kwargs['empty_label'] = _('None') if db_field.blank else None + if 'widget' not in kwargs: + if db_field.name in self.get_autocomplete_fields(request): + kwargs['widget'] = AutocompleteSelect(db_field.remote_field, self.admin_site, using=db) + elif db_field.name in self.raw_id_fields: + kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.remote_field, self.admin_site, using=db) + elif db_field.name in self.radio_fields: + kwargs['widget'] = widgets.AdminRadioSelect(attrs={ + 'class': get_ul_class(self.radio_fields[db_field.name]), + }) + kwargs['empty_label'] = _('None') if db_field.blank else None if 'queryset' not in kwargs: queryset = self.get_field_queryset(db, db_field, request) diff --git a/tests/modeladmin/tests.py b/tests/modeladmin/tests.py index de216cbb118..6934bf2b3c0 100644 --- a/tests/modeladmin/tests.py +++ b/tests/modeladmin/tests.py @@ -437,6 +437,28 @@ class ModelAdminTests(TestCase): ['main_band', 'day', 'transport', 'id', 'DELETE'] ) + def test_raw_id_fields_widget_override(self): + """ + The autocomplete_fields, raw_id_fields, and radio_fields widgets may + overridden by specifying a widget in get_formset(). + """ + class ConcertInline(TabularInline): + model = Concert + fk_name = 'main_band' + raw_id_fields = ('opening_band',) + + def get_formset(self, request, obj=None, **kwargs): + kwargs['widgets'] = {'opening_band': Select} + return super().get_formset(request, obj, **kwargs) + + class BandAdmin(ModelAdmin): + inlines = [ConcertInline] + + ma = BandAdmin(Band, self.site) + band_widget = list(ma.get_formsets_with_inlines(request))[0][0]().forms[0].fields['opening_band'].widget + # Without the override this would be ForeignKeyRawIdWidget. + self.assertIsInstance(band_widget, Select) + def test_queryset_override(self): # If the queryset of a ModelChoiceField in a custom form is overridden, # RelatedFieldWidgetWrapper doesn't mess that up.