#33321: Django admin doesn't render "add another / modify" icons next to 
ForeignKey
fields that are declared in the ModelForm
-----------------------------------------+------------------------
               Reporter:  James Pic      |          Owner:  nobody
                   Type:  Bug            |         Status:  new
              Component:  contrib.admin  |        Version:  3.2
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  1              |
-----------------------------------------+------------------------
 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)

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33321>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/047.05202d99da6261109788e43104ecbb0a%40djangoproject.com.

Reply via email to