I'm building an API using django and the django rest framework. I'm also building a system that will be consuming this API (also Django).
I'm a bit confused as how to implement the serializers on the two servers. So far I've implemented an input and output serializer on both servers. The code example below shows these serializers for a simple example. It takes in a date and a number of days, makes a calculation and returns a new date and the number of holidays between the dates (code does not actually calc this).
There's 4 places where I call a serializer and each time I also have to call the is_valid() method. I'm not sure if all these serializers and calls to is_valid are needed. It all works, but it seems a bit clumsy. Having said that, I'm not sure what other alternatives there are, especially since I need to serialize dates. I guess I can implement my own serializer for dates, but it seems like I'm reinventing the wheel. Then there's also that issue of ensuring the serializtion classes stay the same between the two servers.
My question is basically, is there a recommended approach that should be followed when I'm both the creator and consumer of an API? Do I need all of these serializers? If not, which one(s) can I drop and what should I replace it with?
Note in my actual code I have numerous nested fields in the serializers so it is not as simple as this example.
On my API server I have the following:
from rest_framework import views, serializers
from django.views.decorators.csrf import csrf_exempt
from rest_framework.decorators import api_view
class MyInputSerializer(serializers.Serializer):
my_date = serializers.DateField()
days = serializers.IntegerField()
def do_calc(self):
my_date = self.validated_data.get('my_date')
days = self.validated_data.get('days')
calc_date = my_date # just as an example
holidays = days - 2 # just as an example
result = {
'calc_date': calc_date,
'holidays': holidays,
}
return MyOutputSerializer(data=result)
class MyOutputSerializer(serializers.Serializer):
calc_date = serializers.DateField()
holidays = serializers.IntegerField()
@csrf_exempt
@api_view(['POST'])
def test(request): #/api/v1.0/calc/ maps to this function
data=request.data
serializer = MyInputSerializer(data=data)
if serializer.is_valid(raise_exception=True):
result = serializer.do_calc()
if result.is_valid(raise_exception=True): #should always be valid? Needed to access result.data
return JsonResponse(result.data)
On my normal Django webserver I have the following:
from rest_framework import serializers
from datetime import date
import requests
class MyInputSerializer(serializers.Serializer):
# same fields as above
my_date = serializers.DateField()
days = serializers.IntegerField()
class MyOutputSerializer(serializers.Serializer):
# same fields as above
calc_date = serializers.DateField()
holidays = serializers.IntegerField()
def testing():
MY_SERVER_URL = 'http://127.0.0.1:8888/api/v1.0/calc/'
data = {
'my_date': date(2016, 2, 2),
'days': 10,
}
serializer = MyInputSerializer(data=data)
if serializer.is_valid(raise_exception=True):
post_result = requests.post(MY_SERVER_URL, json=serializer.data)
result = MyOutputSerializer(data=post_result.json())
if result.is_valid(raise_exception=True): # This needed?
calc_date = result.validated_data.get('calc_date')
holidays = result.validated_data.get('holidays')
return calc_date, holidays
One other thing, I can create a ModelSerializer on the server with the DB, but then I need to recreate a normal serializer on the other server to deserialize the data. That sort of negates the advantage of the ModelSerializer. How does one typically deal with this problem?