django.contrib.admin.options.InlineModelAdmin.get_formset is called with
widgets and then:
> django.forms.models.inlineformset_factory (Ok here as widgets are
passed)
> django.forms.models.modelformset_factory (Ok here as widgets are passed)
> django.forms.models.modelform_factory (Ok here as widgets are passed)
> django.forms.models.ModelFormMetaclass.__new__ (Ok as widgets are passed
as attrs)
> django.forms.models.fields_for_model (Ok here too)
> django.contrib.admin.options.BaseModelAdmin.formfield_for_dbfield (Ok
here too as widget is received in kwargs)
Then here comes the problem:
> django.contrib.admin.options.BaseModelAdmin.formfield_for_foreignkey
{{{
def formfield_for_foreignkey(self, db_field, request, **kwargs):
"""
Get a form Field for a ForeignKey.
"""
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 'queryset' not in kwargs:
queryset = self.get_field_queryset(db, db_field, request)
if queryset is not None:
kwargs['queryset'] = queryset
return db_field.formfield(**kwargs)
}}}
This code just ignores the widget sent.
How to fix this? Just change that method to the following:
{{{
def formfield_for_foreignkey(self, db_field, request, **kwargs):
"""
Get a form Field for a ForeignKey.
"""
db = kwargs.get('using')
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)
if queryset is not None:
kwargs['queryset'] = queryset
return db_field.formfield(**kwargs)
}}}
With {{{if 'widget' not in kwargs}}} I let any widget set to be used by
default instead of assigning a new one. That is the only change to fix it.
This way now I am able to use my TabularInline and override get_formset to
show my fields with custom widgets.
--
Ticket URL: <https://code.djangoproject.com/ticket/29901>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* Attachment "mypatch.diff" added.
Patch to fix the issue
* type: Uncategorized => Cleanup/optimization
* needs_tests: 0 => 1
* easy: 1 => 0
* stage: Unreviewed => Accepted
Comment:
Can you add a test to your [https://github.com/django/django/pull/10578
PR] and then uncheck "Needs tests" on the ticket?
--
Ticket URL: <https://code.djangoproject.com/ticket/29901#comment:1>
* owner: nobody => Javier Matos Odut
* status: new => assigned
* version: 2.1 => master
* needs_tests: 1 => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/29901#comment:2>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"3d4d0a25b299a97314582156a0d63d939662d310" 3d4d0a2]:
{{{
#!CommitTicketReference repository=""
revision="3d4d0a25b299a97314582156a0d63d939662d310"
Fixed #29901 -- Allowed overriding an
autocomplete/raw_id_fields/radio_fields widget with
ModelAdmin.get_formset().
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29901#comment:3>