Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rename (exposed in API) filter field name using django-filters?

As the question states - I'm trying to rename the filter field name exposed in my API.

I have the following models:

class Championship(Model):
    ...

class Group(Model):
    championship = ForeignKey(Championship, ...)

class Match(Model):
    group = ForeignKey(Group, ...)

I have exposed all of these models in REST API. I've defined filter_fields for the Match model:

class MatchViewSet(ModelViewSet):
    filter_fields = ['group__championship']
    ...

This way, I can filter for specific championship's matches (tested and working):

curl /api/matches/?group__championship=1

Is is possible to use some kind of alias for the exposed filter so I can use the following:

curl /api/matches/?championship=1

where championship in this case will be an alias for group__championship?

pip freeze returns:

django-filter==0.15.2
(...)

I've also tried implementing custom FilterSet with ModelChoiceFilter and custom lookup method:

class MatchFilterSet(FilterSet):
    championship = ModelChoiceFilter(method='filter_championship')

    def filter_championship(self, queryset, name, value):
        return queryset.filter(group__championship=value)

    class Meta:
        model = Match
        fields = ['championship']

With view:

class MatchViewSet(ModelViewSet):
    filter = MatchFilterSet
    (...)

But with no luck. The filter_championship method was even never called.

like image 648
Tomasz Dzieniak Avatar asked Oct 12 '16 07:10

Tomasz Dzieniak


2 Answers

You need to provide model field as name in django_filters with field type. I am considering you are trying to filter by championship id.

class MatchFilterSet(FilterSet):
    championship = django_filters.NumberFilter(field_name='group__championship_id')

    class Meta:
        model = Match
        fields = ['championship']
like image 152
Naresh Avatar answered Nov 12 '22 21:11

Naresh


After Naresh response I have figured out the source of error.

It was the implementation of the model's view:

class MatchViewSet(ModelViewSet):
    filter = MatchFilterSet
    (...)

For django-filter it should be filter_class rather than filter, so the correct implementation is:

class MatchViewSet(ModelViewSet):
    filter_class = MatchFilterSet
    (...)

Also, I've changed the implementation of the model's filter to be more like Naresh suggested:

class MatchFilterSet(FilterSet):
    championship = NumberFilter(field_name='group__championship')

    class Meta:
        model = Match
        fields = ['championship']

The difference between above and the Naresh's one is the luck of _id part which is not necessary.

After these changes everything works fine.

like image 38
Tomasz Dzieniak Avatar answered Nov 12 '22 20:11

Tomasz Dzieniak