How to create an easy Restful API for a simple model(Part II)

How to create an easy Restful API for a simple model(Part II)

In the previous post ( I explained a little bit how to create a basic API for a City model. I used our home page in order to create the serializer, modelviewset and url needed to our first move.

However we usually need more things like the ability to sort, search or filter the data, and the ability to limit how many records we want so we don't get too many in one shot.

In Django Rest framework this is very easy. We use filters that we set a attributes of the ModelViewSet class. Let me put an example with City model again.

Please install django-filter before following this tutorial.

pip install django-filter


from rest_framework import filters

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',)

So by setting filter_backends we are specifing we are going to search, sort and filter the responses. And by setting search_fields we specify which fields we are going to use. The same for ordering and filter. This way of doing things is very similar to Django admin so it is very easy to remember what you need to do even when you not really creatign code related to Rest API. 

Of course, sometimes filters are complicated and need an extra work. For example, if you have model with a datetime field called date, you may want to add two extra parameters like start and end to get a particular period. In this case you can add a FilterClass 

class DateFilter(django_filters.FilterSet):
start_date = django_filters.DateFilter(name="date", lookup_type='gte')
end_date = django_filters.DateFilter(name="date", lookup_type='lte')

class Meta:
model = DateModel
fields = ['other_field', 'start_date', 'end_date']

and then set the 

filter_class = DateFilter

 attribute inside your ModelViewSet class.


In order to only get pagination you have several options and they are in rest_framework.pagination. In my case I like LimitOffsetPagination so we pass limit and offset as a paramenters in the get request and the query is sliced to only get for us the rows we need. For example, to get the first 10 elements you  should send /api/v1/cities/?limit=10&offset=0. To get the next 10, easy again, /api/v1/cities/?limit=10&offset=10.

How can you configure this for the whole API?

You insert this chunk of code in your settings file and you are done.

# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 25,

The page_size parameters represents how many records you will allow by default if limit is not specified in the request.

I think with this very basic tutorial and  the documentation in we are ready to get into more complicated stuff.

Good luck.

Current rating: 2.8