"form" definition on "class Meta" of a FilterSet is not honored
DanielSwain opened this issue · 3 comments
I need to modify what is displayed to the user for each item in a <select>
by including in parentheses the count of a set of items that ForeignKey
to the main model. To do this, I defined a custom form and fields (including a queryset definition on the field displayed in the <select>
- see the very end of this question for additional information). I was getting KeyError
on the first of the field names, so I then stripped down the form definition by simply declaring a filter form of type forms.ModelForm
with exclude
:
class MyModelFilterForm(forms.ModelForm):
class Meta:
model = MyModel
exclude = ['field1', 'field2']
# fields = ['field1', 'field2', 'field3', 'field4', 'field5', etc.]
class MyModelFilter(django_filters.FilterSet):
class Meta:
form = MyModelFilterForm
As I add each subsequent field from the fields in the model definition to exclude
, I then get a KeyError
on the next, non-excluded field. It seems like the form
declaration isn't being honored. I looked at your source code in BaseFilterSet.get_fields().
It appears that the form
argument is possibly not being taken into account in get_fields()
. Is that right, or am I missing something?
Incidentally, in order to modify what is displayed for each item in the <select>
, I defined a custom ModelChoiceField
and used the label_from_instance
method as mentioned here.
class MyCustomChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return f"{obj.name} ({obj.relatedmodel_set.count()})"
There will only ever be a small number of items in the <select>
, and I included select_related
for related_model
on the queryset definition.
Hi @DanielSwain. The Meta.form
attribute is used in get_form_class()
, where it's used as the base for a new class built with fields for the declared filters.
You may want to override that, e.g. if your form has exact fields specified, or to control the dynamic generation.
Thank you @carltongibson. I did notice get_form_class()
and the comment in the code there:
A search in the docs on get_form_class
turns up nothing, so this appears to be an undocumented feature(?). 😊 Also, while setting a form
attribute seems like the most acceptable and most standard way to use a custom form in a FilterSet
, the statement in the docs that one can set a form
attribute on a FilterSet
appears to not be applicable. Is that correct? None of this is a criticism of this excellent library. I just want to make sure things are clear for the record. In my ideal world, I would be able to assign a custom form to the form
attribute as is currently stated in the docs.
... the statement in the docs that one can set a form attribute on a FilterSet appears to not be applicable.
I would be able to assign a custom form to the form attribute as is currently stated in the docs.
You can. You can see in the code there that self._meta.form
is used as the base class for the dynamically generated form class used by the filterset.
this appears to be an undocumented feature(?)
Yes, good. Adding that to the FilterSet reference would be great.