I'm using the Django REST framework, and I have a view set with an extra list route method. How can I get that method's URL included in the API root page?
Here's a simplified version of my view set:
class BookViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = (permissions.IsAuthenticated, )
    @list_route(methods=['get'])
    def featured(self, request):
        queryset = self.filter_queryset(self.get_queryset()).filter(featured=True)
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
I register the view set in urls.py:
router = DefaultRouter()
router.register('books', BookViewSet)
urlpatterns = patterns(
    url(r'^api/', include(router.urls), name='api_home'),
    #...
    )
The URL for books/featured is routed properly, but when I go to http://localhost:8000/api, I only see this:
HTTP 200 OK
Content-Type: application/json
Vary: Accept
Allow: GET, HEAD, OPTIONS
{
    "books": "http://localhost:8000/api/books/"
}
How can I get an entry added for something like this?
"book-featured-list": "http://localhost:8000/api/books/featured"
                You could try to inherit from DefaultRouter which is responsible for api root view and redefine get_api_root_view method.
class MyRouter(routers.DefaultRouter):
    def get_api_root_view(self):
        """
        Return a view to use as the API root.
        """
        api_root_dict = OrderedDict()
        list_name = self.routes[0].name
        for prefix, viewset, basename in self.registry:
            api_root_dict[prefix] = list_name.format(basename=basename)
        class APIRoot(views.APIView):
            _ignore_model_permissions = True
            def get(self, request, *args, **kwargs):
                ret = OrderedDict()
                namespace = request.resolver_match.namespace
                for key, url_name in api_root_dict.items():
                    if namespace:
                        url_name = namespace + ':' + url_name
                    try:
                        ret[key] = reverse(
                            url_name,
                            args=args,
                            kwargs=kwargs,
                            request=request,
                            format=kwargs.get('format', None)
                        )
                    except NoReverseMatch:
                        # Don't bail out if eg. no list routes exist, only detail routes.
                        continue
                ret['book-featured-list'] = '%s%s' % (ret['books'], 'featured/')
                return Response(ret)
        return APIRoot.as_view()
P.S. sorry, didn't see your comment before I posted the answer
You can install package django-rest-swagger, just follow here: https://github.com/marcgibbons/django-rest-swagger
It is more powerful than DRF's api list page. It will list all the rest apis (include list_route/detail_route apis) for your modules, and you can also do some api test (CRUD) on the page.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With