django-filter: Using ChoiceFilter with choices dependent on request
Asked Answered
C

1

6

I am using django-filter and need to add a ChoiceFilter with choices dependent on the request that I receive. I am reading the docs for ChoiceFilter but it says: This filter matches values in its choices argument. The choices must be explicitly passed when the filter is declared on the FilterSet.

So is there any way to get request-dependent choices in the ChoiceFilter?

I haven't actually written the code but the following is what I want -

class F(FilterSet):
    status = ChoiceFilter(choices=?) #choices depend on request
    class Meta:
        model = User
        fields = ['status']
Consistency answered 20/12, 2018 at 9:52 Comment(4)
Did you look at this? Your FilterSet is initialised with the request (which may be None so you should check), so you can use request object in the filter's __init__() method and declare the status field there.Rebeca
You can also use a custom method which has access to the filterset's request property.Rebeca
@Rebeca I tried doing self.fields['status'] = ChoiceFilter(choices=...) in __init__ but was getting some error. I'm currently out so cannot check but iirc the problem was with self.fields['status'] being set like this.Consistency
@Rebeca Sorry I just came back and checked. I get the following error: 'F' object has no attribute 'fields'Consistency
T
5

I've been looking too hard that I found two different ways of doing it! (both by overriding the __init__ method). Code inspired from this question.

class LayoutFilterView(filters.FilterSet):
    supplier = filters.ChoiceFilter(
        label=_('Supplier'), empty_label=_("All Suppliers"),)

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

        # First Method
        self.filters['supplier'].extra['choices'] = [
            (supplier.id, supplier.id) for supplier in ourSuppliers(request=self.request)
        ]

        # Second Method
        self.filters['supplier'].extra.update({
            'choices': [(supplier.id, supplier.name) for supplier in ourSuppliers(request=self.request)]
        })

The function ourSuppliers is just to return a QuerySet to be used as choices

def ourSuppliers(request=None):
    if request is None:
        return Supplier.objects.none()

    company = request.user.profile.company
    return Supplier.objects.filter(company=company)
Toddler answered 28/10, 2019 at 2:45 Comment(2)
Where is 'ourSuppliers' being defined here?Autophyte
I added the definition of ourSuppliers .. it's just a function to return the desired QuerySet to be used as your choicesToddler

© 2022 - 2024 — McMap. All rights reserved.