Opened 9 years ago
Last modified 8 months ago
#25887 new Cleanup/optimization
Clarify support for ForeignKey and form fields other than ModelChoiceField — at Initial Version
Reported by: | Miriam Gershenson | Owned by: | nobody |
---|---|---|---|
Component: | Documentation | Version: | dev |
Severity: | Normal | Keywords: | ModelForm, ForeignKey |
Cc: | benjaminjkraft@…, Ülgen Sarıkavak | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I'm maintaining a project which has a similar situation to #23795: we have an ajax autocomplete form field for ForeignKeys, which in our case inherits from forms.IntegerField
. We also have a custom model field which subclasses ForeignKey in order to override formfield()
and specify our custom form field as the default.
When we updated from Django 1.6 to 1.8, ModelForms for all models using this field started erroring on import because of the limit_choices_to
keyword argument getting inserted by RelatedField.formfield()
, not being handled by our form field (which has no support for limit_choices_to
because we haven't needed it), and eventually being passed to the Field
constructor through some super()
calls.
Here is a simple example of the error:
class CustomForeignKey(models.ForeignKey): def formfield(self, **kwargs): defaults = {'form_class': IntegerField} # or a subclass of IntegerField defaults.update(kwargs) return super(CustomForeignKey, self).formfield(**defaults) class Target(models.Model): pass class NormalFKModel(models.Model): fk = models.ForeignKey(Target) class CustomFKModel(models.Model): fk = CustomForeignKey(Target) # This will work fine until I try to submit the form class NormalFKModelForm(forms.ModelForm): fk = IntegerField() class Meta: model = NormalFKModel fields = '__all__' # This will error on import on all Django versions class CustomFKModelForm(forms.ModelForm): class Meta: model = CustomFKModel fields = '__all__'
A similar error happens even on older Django, or when I add a workaround for limit_choices_to
only; the code I had which worked on 1.6 already included some workarounds for a few other similar issues, which I hadn't been aware of.
The documentation on overriding formfield() doesn't mention this pitfall, and neither does the form field documentation, or any other relevant documentation I could find.
Ideally, both of the ModelForm
examples above would display without erroring, and would work correctly if the forms.IntegerField
is replaced by a subclass which normalizes to model instances rather than integers, especially considering that one of them already meets those conditions. Alternatively, I would also consider this fixed if some documentation were added on special requirements for custom form fields that will be used for ForeignKeys.