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