How do you get that standard ForeignKey select box with the “+” add
another icon next to it on your form? This post will take you through the
steps that I took to get the ForeignKey working like it does in the Django
admin.
How does the Django admin create a ForeignKey select field
Django creates a forms.ModelChoiceField with queryset and to_field_name
arguments as the default form field for a foreignkey. To see for yourself,
have a look at django.db.models.fields.related.py under the ForeignKey
class and method formfield
here.
Now we know to use the ModelChoiceField. But what about those
arguments queryset and to_field_name, and how does the “+” add icon
appear?
The queryset argument should be a queryset or manager for the model your
ForeignKey is to. For the following example:
1 2 | |
We are trying to build a form.Form with a ForeignKey type field to SpaceCompany we might use:
1
| |
I don’t know what to_field_name does. So I’ve left it out of this
discussion. Don’t worry though, to_field_name, will appear later on.
How Django admin adds that “+” add icon
Django actually replaces the default select widget on the ModelChoiceField
with its own django.contrib.admin.widgets.RelatedFieldWidgetWrapper. This
swap occurs in django.contrib.admin.options near the
top of the file
in formfield_for_dbfield method of the BaseModelAdmin class. This code is
interesting for two reasons:
- It checks if the current user has permission to add a new
SpaceCompany - The
RelatedFieldWidgetWrapperrequires knowledge of theadmin_site
But where can I make this widget swap occur? and how do I get an instance of admin_site?
This will largely depend on how and why you are using the forms.Form in the
first place. I was using the forms.Form as one of the FormWizard’s forms.
So in render_template I was able to create a hook that checked the form for
any ModelChoice fields and did the switch, and checked for permissions. I
had a copy of the admin_site on my FormWizard thanks to this article onFormWizard in the Django admin. If you were not using
ModelChoiceField in the admin, then you probably don’t need that “+” add
another icon, because it is created using the reverse of admin_site.name
amongst other things (more details in django.contrib.admin.widgets.py class
RelatedFieldWidgetWrapper)
Python for Power Systems