Python – django Rest Framework – ViewSet with custom ListView and URL parameters

django Rest Framework – ViewSet with custom ListView and URL parameters… here is a solution to the problem.

django Rest Framework – ViewSet with custom ListView and URL parameters

I have the following settings:

I would like to list all holidays for a specific year. That’s why I omitted the default ListView and implemented my own ListView like this:

class HolidayViewSet(mixins. RetrieveModelMixin, GenericViewSet):
@list_route()
def year(self, request, year=get_today().year):
    public_holidays = self.get_queryset().filter(date__year=year)
    page = self.paginate_queryset(public_holidays)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        return self.get_paginated_response(serializer.data)
    serializer = self.get_serializer(public_holidays, many=True)
    return Response(serializer.data)

If I use the default value /holiday/year/, I get the results for that year.

But when I try to pass a parameter, I get a 404. The 404 page (in Debug mode) even showed me the correct URL pattern:

api/v1/ ^holiday/year/$ [name='holiday-year']
api/v1/ ^holiday/year\. (? P<format>[a-z0-9]+)/?$ [name='holiday-year']

In documentation unfortunately this aspect is not covered.

Any idea why my route to holiday/year/2017 didn’t work?

Solution

Ok, my workaround is to use django-filter.

My filter:

class HolidayFilter(filters. FilterSet):
    """
    This filter can be used to filter holidays by different values in API views or viewsets.
    See http://django-filter.readthedocs.io/en/1.1.0/guide/rest_framework.html
    """
    year = filters. NumberFilter(name='date', lookup_expr='year')

class Meta:
        model = Holiday
        fields = ['date']

My opinion:

class HolidayListViewSet(ModelViewSet):

def list(self, request, *args, **kwargs):
        # Apply filters
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        # Pagination
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        # Serializer
        serializer = self.get_serializer(queryset, many=True)
        # Response
        return Response(serializer.data)

Website:

/api/v1/holiday/?year=2016

Related Problems and Solutions