Swagger: How to create an easy Restful API for a simple model in Django(Part IV)

How to create an easy Restful API for a simple model in Django(Part IV)

If you have been following the previous 3 posts you have now your API 'running'(not deployed yet in production) but you may need to allow your customers to understand your API. In other words, you documentation for your API. Today the winning in that space is Swagger and it can be used not only for Python and Django but almost for every web framework available today. It is Open Source so you can even contribute to the project if your language or framework is not yet supported.

Most of the time you work for a Company that is not really making the API available to the public but you still should document your APIs so UI developers(including yourself sometimes) can understand and test your APIs.

Let's get to work. 

First we need to install the swagger app.

pip install django-rest-swagger

If you go their website documentation(http://django-rest-swagger.readthedocs.org/en/latest/) you will get a quick start.

  • Add rest_framework_swagger to Django settings INSTALLED_APPS
INSTALLED_APPS = (
    ...
    'rest_framework_swagger',
)
  • Include the rest_framework_swagger URLs to a path of your choice
patterns = ('',
    ...
    url(r'^docs/', include('rest_framework_swagger.urls')),
)

Further configuration can be made via SWAGGER_SETTINGS in your project’s settings.py.

OK, it is an start but once you browse to your docs urls you will notice that you are no able to filter if you only do what they say there. How can we add parameters to our list API. 

The way you allow swagger to know about your params is using --. For example,

status -- status separated by commas

But without some hint with django rest framework it will not be able to guess your filters and other parameters that you may be handling in get_queryset method.

In order to fix you can look at the ModelViewSet class:

class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass

So you realize that the list method shoud be defined in mixins.ListModelMixin. 

class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())

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)

You just need to create your ViewSet class and put your comments inside the list method.

class CityViewSet(viewsets.ModelViewSet):
    model = City
    serializer_class = CitySerializer
    queryset = City.objects.all()
filter_backends = (filters.SearchFilter, filters.OrderingFilter, filters.DjangoFilterBackend)
search_fields = ('zip_code', 'city')
ordering_fields = ('zip_code', 'city')
filter_fields = ('state',)

def
list(self, request, *args, **kwargs):
"""
state -- state (US state)
"""
return super(CityViewSet, self).list(request, *args, **kwargs)

This way you will not only be able to post/retreive/delete a city by also you will be able to list all cities and filter cities by states form the documentation of your API.

We still are missing deployment, and how to log what is happening inside our apis. Let's talk about that in our next blog post.

Current rating: 1