﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33321	"Django admin doesn't render ""add another / modify"" icons next to ForeignKey fields that are declared in the ModelForm"	James Pic	nobody	"Django admin renders very convenient ""add another"" and ""modify"" buttons next to ForeignKey fields when the admin uses a form like this:

{{{
class TForm(forms.ModelForm):
    class Meta:
        model = TModel
        fields = ('name', 'test')
        widgets = {
            'test': MyWidget(),
        }

class TAdmin(admin.ModelAdmin):
    form = TForm
}}}

BUT, it won't if my field is declared in the ModelForm as such:

{{{
class TForm(forms.ModelForm):
    test = forms.ModelChoiceField(
        widget=MyWidget(),
        queryset=Some.objects.all(),
    )
    class Meta:
        model = TModel
        fields = ('name', 'test')
        

class TAdmin(admin.ModelAdmin):
    form = TForm
}}}

This is confusing behavior is not documented AFAIK, and users have been opening issues on github about this, I just debugged it out by chance because it was in my way.

This is because Django admin:

- Does the formfield.widget = RelatedFieldWidgetWrapper(formfield.widget) decoration on generated fields
- And then overrides generated fields with the declared fields

As you can see in this trace session:

{{{
> /home/jpic/.local/lib/python3.9/site-packages/django/forms/models.py(279)__new__()
-> fields.update(new_class.declared_fields)
(Pdb) l
274  	                message = message % (', '.join(missing_fields),
275  	                                     opts.model.__name__)
276  	                raise FieldError(message)
277  	            # Override default model fields with any custom declared ones
278  	            # (plus, include all the other declared fields).
279  ->	            fields.update(new_class.declared_fields)
280  	        else:
281  	            fields = new_class.declared_fields
282
283  	        new_class.base_fields = fields
284
(Pdb) fields
{'name': <django.forms.fields.CharField object at 0x7f0a251cf0d0>, 'test': <django.forms.models.ModelChoiceField object at 0x7f0a251cf9a0>}
(Pdb) fields.declared_fields
*** AttributeError: 'dict' object has no attribute 'declared_fields'
(Pdb) new_class.declared_fields
{'test': <dal_alight.fields.ModelAlight object at 0x7f0a283b6460>}
(Pdb) new_class.declared_fields['test'].widget
<dal_alight.fields.ModelAlightWidget object at 0x7f0a283b6520>
(Pdb) fields['test'].widget
<django.contrib.admin.widgets.RelatedFieldWidgetWrapper object at 0x7f0a251cfdf0>
}}}

I believe that Django should always decorate related field widgets with RelatedFieldWidgetWrapper, unless the widget is explicitely incompatible with it. The meta code for this proposal is: if not getattr(formfield.widget, 'incompatible_with_related_field_widget_wrapper', False): formfield.widget = RelatedFieldWidgetWrapper(formfield.widget)"	Bug	closed	contrib.admin	3.2	Normal	wontfix			Unreviewed	0	0	0	0	0	1
