Search code examples
pythondjangorestdjango-filter

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.


Solution

  • 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.