django-filter icon indicating copy to clipboard operation
django-filter copied to clipboard

No clean way to override empty label for ModelChoiceFilter and ModelMultipleChoiceFilter

Open Alex-Sichkar opened this issue 4 years ago • 2 comments

ModelChoiceFilter and ModelMultipleChoiceFilter don't accept empty_label argument like ChoiceFilter and MultipleChoiceFilter do. I work around this problem by overriding form filed empty label in __init__ method like self.form.fields['filed_name'].empty_label = 'Custom label'. I can live with it but there is very strange issue - if I override the filter querysets as well like:

class MyModelFilter(FilterSet):
    user = django_filters.ModelMultipleChoiceFilter(queryset=None)
    project = django_filters.ModelMultipleChoiceFilter(queryset=None)

    class Meta:
        model = MyModel
        fields = ['user',  'project']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.filters['user'].queryset = User.objects.custom()
        self.form.fields['user'].empty_label = 'Custom label'

        self.filters['project'].queryset = Project.objects.custom()
        self.form.fields['project'].empty_label = 'Custom label'

I get an error: 'NoneType' object has no attribute 'none' but if I put all the empty labels overrides AFTER all the queryset overrides like:

    self.filters['user'].queryset = User.objects.custom()
    self.filters['project'].queryset = Project.objects.custom()

    self.form.fields['user'].empty_label = 'Custom label'
    self.form.fields['project'].empty_label = 'Custom label'

There is no error.

Alex-Sichkar avatar Dec 01 '20 10:12 Alex-Sichkar

Hi @Alex-Sichkar,

while I was digging into your issue I could reproduce it for the ModelMultipleChoiceFilter but not for the ModelChoiceFilter, with my implementation you can use the following approach without raising any error.

    user = django_filters.ModelChoiceFilter(queryset=None, empty_label='Custom label')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.filters['user'].queryset = User.objects.custom()

Perhaps, you don't even need to override the queryset after the initialization but that's up to you.

Secondly, in case that you would like to use the ModelMultipleChoiceFilter then the error isn't coming from the django-filter library but from Django and especially https://github.com/django/django/blob/76c0b32f826469320c59709d31e2f2126dd7c505/django/forms/models.py#L1317 when they are calling it with empty_label=None.

Now I guess it's time to ask my question, why do you need to override the empty_label field of a ModelMultipleChoiceFilter, I guess that this should be None, right? I really want to check your case to understand your problem.

panosangelopoulos avatar Apr 01 '21 08:04 panosangelopoulos

Hi, @panosangelopoulos. Sorry for late answer. My use case is to show custom label for resetting the filter. Imagine you have a filter for a field named status and you want to show something like Any status instead of dashes. Regarding to ModelChoiceFilter, it seems I was wrong.

Alex-Sichkar avatar Oct 09 '21 09:10 Alex-Sichkar