Django Location app Rest API
By: Saeed Babashahi
Tags: Django Rest Framework, Rest Api, Location, Django

We want to add support Rest API to our app. This feature allows other applications (like an android app or your website) connect to your app through network and utilize it. For this feature I use Django Rest Framework. DRF is a powerful framework that adds the ability of building Web APIs to your Django app.

First Install DRF by using bellow command.

pip install djangorestframework

Now add djangorestframework to INSTALLED_APPS settings.py . Then add serializers.py to your app. Now your structure looks like bellow.

App structure

Add bellow code to serializers.py .

import json



from django.contrib.gis.geos import Point

from rest_framework import serializers



from location.models import Location



class LocationSerializer(serializers.Serializer):

id = serializers.ReadOnlyField()

location = serializers.ListField(child=serializers.DecimalField(max_digits=7, decimal_places=5), max_length=2, min_length=2)



def create(self, validated_data):

validated_data['location_point'] = Point(validated_data.pop('location'))

location = Location(**validated_data)

location.save()

return location



def update(self, instance, validated_data):

if validated_data.get('location'):

instance.location_point = Point(validated_data.pop('location'))

return instance



def to_representation(self, instance):

instance.location = json.loads(instance.location_point.geojson)['coordinates']

instance = super().to_representation(instance)

return instance

In LocationSerializer class we have location and id field. Django by default adds id column to your model. It is your primary key. Location field is used for receiving and sending data through API. It’s a list containing 2 decimal fields. We will use create function on posting data to create new item in our app, update function on patch or putting data to update an existing item in our app. validated_data is data that comes through API. That data will be validated by our serializer. So we know data must be a list of two decimals. instance is the object that we want to update.

DRF can convert many different kinds of fields like string and integers. But for a location field we need to convert it by utilizing to_representation function. In this function we convert location_point to a list of two decimals.

It may come to your mind why we need a list of 2 decimals? Since a location has x and y axis which in geometry are called Latitude and longitude.

Now we must use our serializer in our view.

import json



from django.http import HttpResponse

from rest_framework import generics

from rest_framework.exceptions import ValidationError



from geoapp.models import Location

from geoapp.serializers import LocationSerializer





class CreateView(generics.CreateAPIView):

serializer_class = LocationSerializer

model = Location



def post(self, request, *args, **kwargs):

try:

serialize_data = self.get_serializer(data=request.data)

if serialize_data.is_valid(raise_exception=True):

self.perform_create(serialize_data)

return HttpResponse(

json.dumps({}),

status=201,

content_type="application/json"

)

except ValidationError as e:

return HttpResponse(

json.dumps({'message': e.detail}),

status=400,

content_type="application/json"

)





class UpdateView(generics.UpdateAPIView):

serializer_class = LocationSerializer

model = Location



def put(self, request, id, *args, **kwargs): # need full required parameters

try:

instance = self.model.objects.get(id=id)

serialize_data = self.get_serializer(instance, data=request.data)

if serialize_data.is_valid(raise_exception=True):

self.perform_update(serialize_data)

data = self.get_serializer(instance)

return HttpResponse(

json.dumps({'data': data.data}),

status=200,

content_type="application/json"

)

except self.model.DoesNotExist as d:

return HttpResponse(

json.dumps({'message': 'Instance does not exist.'}),

status=404,

content_type="application/json"

)

except ValidationError as e:

return HttpResponse(

json.dumps({'message': e.detail}),

status=400,

content_type="application/json"

)



def patch(self, request, id, *args, **kwargs): # just send parameters you want to update, don't need to send them all

try:

instance = self.model.objects.get(id=id)

permissions.check_perm_owner_update(request, instance)



serialize_data = self.get_serializer(instance, data=request.data, partial=True)

if serialize_data.is_valid(raise_exception=True):

self.perform_update(serialize_data)

data = self.get_serializer(instance)

return HttpResponse(

json.dumps({'data': data.data}),

status=200,

content_type="application/json"

)

except self.model.DoesNotExist as d:

return HttpResponse(

json.dumps({'message': 'Instance does not exist.'}),

status=404,

content_type="application/json"

)

except ValidationError as e:

return HttpResponse(

json.dumps({'message': e.detail}),

status=400,

content_type="application/json"

)





class ListView(generics.ListAPIView):

serializer_class = LocationSerializer

model = Location



def get(self, request, *args, **kwargs):

result = self.model.objects.all()

data = self.get_serializer(result, many=True)

return HttpResponse(

json.dumps({'data': data.data}),

status=200,

content_type="application/json"

)

In this code we add 3 class views for creating, updating and getting a list of items. By setting serializer_class view will connect our view to serializer and based on our instructions it will create, update or serialize data . We need to add urls to these views something like bellow.

path('create/', views.CreateView.as_view()),

path('list/', views.ListView.as_view()),

path('<int:id>/update/', views.UpdateView.as_view()),

And that was the end of coding. You can use your Rest API with postman. You can create new items by using POST http request.

Create item

Getting list of items by using GET http request.

List items

And moreover updating an instance by using PUT or PATCH http request.

update an item

Feel free to comment any problems and issues with this article, I will be glad to learn from you.