Django Rest Framework is very powerful web API framework with built-in class based API views and serializers. Despite of having numerous features, DRF lets you to customize deeply.
In this blogpost, I’d like to serialize items with JSON Object instead of JSON Array.
BTW, We can say that JSON Object is equivalence of Python dictionary and JSON Array is for Python list.
Here is the traditional List API view response. There are list of book items which are compound in list.
[
{
"id": 1,
"title": "The Man in the High Castle",
"writer": "Philip K. Dick",
"isbn": "9780679740674"
},
{
"id": 2,
"title": "B Is for Beer",
"writer": "Tom Robbins",
"isbn": "9780061687273"
},
{
"id": 3,
"title": "Tales of Nasrettin Hoca",
"writer": "Aziz Nesin",
"isbn": "9789759548100"
}
]
However, API Consumer sometimes would like to go over the response more easily. Imagine this scenario, Frontend would like to reach writer of the book immediately with it’s ISBN. In traditional way, FE will iterate over all list items and look it’s ISBN is correct or not. If so, It returns value of writer keyword in book object.
In this case, Bundle like below will be more useful for the API Consumer. There are items bundled with-in their ISBN numbers.
{
"9780679740674": {
"id": 1,
"title": "The Man in the High Castle",
"writer": "Philip K. Dick"
},
"9780061687273": {
"id": 2,
"title": "B Is for Beer",
"writer": "Tom Robbins"
},
"9789759548100": {
"id": 3,
"title": "Tales of Nasrettin Hoca",
"writer": "Aziz Nesin"
}
}
We can easily implement a mixin and use it with ModelSerializer
. In the mixin, We just need to override to_representation()
method of ModelSerializer
and ListSerializer
.
# books/mixins.py
from rest_framework.serializers import ListSerializer as DRFListSerializer
class UniqueFieldMixin(object):
unique_lookup_field = 'id'
def to_representation(self, instance):
bundle = super().to_representation(instance)
lookup_value = str(bundle.get(self.unique_lookup_field))
bundle.pop(self.unique_lookup_field)
return {lookup_value: bundle}
class ListSerializer(DRFListSerializer):
def to_representation(self, data):
from collections import OrderedDict
context = OrderedDict()
for item in data:
context.update(self.child.to_representation(item))
return context
@property
def data(self):
return super(DRFListSerializer, self).data
Set the field which will be key of the bundle in unique_lookup_field
. Use the UniqueFieldMixin.ListSerializer
as a list_serializer_class
.
# books/serializers.py
from books.mixins import UniqueFieldMixin
from books.models import Book
from rest_framework.serializers import ModelSerializer
class BookSerializer(UniqueFieldMixin, ModelSerializer):
unique_lookup_field = 'isbn'
class Meta:
model = Book
fields = ('id', 'title', 'writer', 'isbn')
list_serializer_class = UniqueFieldMixin.ListSerializer
That’s it!
This post first appeared on FG · A Blog About Computer Science By, please read the originial post: here