[Django]-Django Rest Framework โ€“ ViewSet with custom list view and URL parameter

3๐Ÿ‘

โœ…

Ok, my workaround is using 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 viewset:

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)

The URL:

/api/v1/holiday/?year=2016
๐Ÿ‘คRon

0๐Ÿ‘

DRF differentiates list and detail requests. list request is not expected to have additional path parameter(i.e. /{id}), while detail request, in opposite, defined by it.

What it means is @list_route decorator creates /holiday/year endpoint, and @detail_route will create /holiday/{id}/year endpoint.

0๐Ÿ‘

I think my approach is so simple but its useful. just determine your Router like below:

urlpatterns += [
    path(r'holiday/<int:year>/', TestListView.as_view()),
]

The URL:

api/v1/holiday/2016/

Then create your view like this:

class TestListView(generics.ListAPIView):
    serializer_class = TestSerializer

    def get(self, request, *args, **kwargs):
        year = kwargs.get('year', '')
        query_set = Test.objects.filter(year__exact=year) # Test is my test model
        serializer = self.get_serializer(query_set, many=True)
        return Response(serializer.data)
๐Ÿ‘คEhsan Ahmadi

Leave a comment