XML response in Django using Django-rest-framework
In this article, we shall see how to return the response from our Django project in XML format instead of the traditional JSON response. We have to install a third-party package first in order to render XML response.
REST Framework XML provides a simple informal XML format. It was previously included directly in the REST framework package and is now instead supported as a third-party package.
Installation & configuration
We can install the package easily using pip as follows:
$ pip install djangorestframework-xml
Modify your REST framework settings.
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework_xml.parsers.XMLParser',
],
'DEFAULT_RENDERER_CLASSES': [
'rest_framework_xml.renderers.XMLRenderer',
],
}
If we add this to the settings.py file, the responses from all the APIs will be rendered in XML only. In other words, setting the DEFAULT_RENDERER_CLASSES
to 'rest_framework_xml.renderers.XMLRenderer'
will result in rendering all the response in XML format only.
If we want only certain APIs to return response we can add a parameter called renderer_classes = [MyXMLRenderer, ] to each individual class-based view function.
This is how we can add renderer_classes to each individual class-based function.
This is how the response will look like before and after modifying the renderer class.
[
{
"id": 1,
"name": "Montfort",
"email": "montfort@gmail.com",
"address": "12, New foundland, USA",
"student_count": 4
},
{
"id": 2,
"name": "Vidyashram",
"email": "Vidyashramschool@gmaill.com",
"address": "Chennai",
"student_count": 0
}
]
This is the default JSON response.
<root>
<list-item>
<id>1</id>
<name>Montfort</name>
<email>montfort@gmail.com</email>
<address>12, New foundland, USA</address>
<student_count>4</student_count>
</list-item>
<list-item>
<id>2</id>
<name>Vidyashram</name>
<email>Vidyashramschool@gmaill.com</email>
<address>Chennai</address>
<student_count>0</student_count>
</list-item>
</root>
And this is how the XML response looks like after adding the renderer_class attribute.
Note that by default the tag name of the root element is “root” and the individual item tag name is “list-item”.
We can override this by creating a custom class extending the XMLRenderer class.
Let us say I want my root element tag should be named as “schools”. In that case, I can extend the XMLRenderer class and create my own class like this.
from rest_framework_xml.renderers import XMLRendererclass MyXMLRenderer(XMLRenderer):
root_tag_name = 'schools'class SchoolView(APIView):
renderer_classes = [MyXMLRenderer, ] def get(self, request):
schools = School.objects.all()
school_serializer = SchoolListSerializer(schools, many=True)
return Response(school_serializer.data)
I have replaced the class name in the renderer_classes with my custom class. The attribute to modify the root tag name is root_tag_name.
Now my output would like this.
<schools>
<list-item>
<id>1</id>
<name>Montfort</name>
<email>montfort@gmail.com</email>
<address>12, New foundland, USA</address>
<student_count>4</student_count>
</list-item>
<list-item>
<id>2</id>
<name>Vidyashram</name>
<email>Vidyashramschool@gmaill.com</email>
<address>Chennai</address>
<student_count>0</student_count>
</list-item>
</schools>
Since the list-item is just a list of schools under the root “schools” tag I would like to rename them as “school” instead of “list-item”.
I have to add an additional attribute to my custom XMLRenderer class. The attribute to modify the “list-item” tag name is “item_tag_name”.
Adding this attribute to the custom XMLRenderer class, now my code will look like this.
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_xml.renderers import XMLRendererfrom student.models import School
from student.serializers import SchoolListSerializer
class MyXMLRenderer(XMLRenderer):
root_tag_name = 'schools'
item_tag_name = 'school'
class SchoolView(APIView):
renderer_classes = [MyXMLRenderer, ] def get(self, request):
schools = School.objects.all()
school_serializer = SchoolListSerializer(schools, many=True)
return Response(school_serializer.data)
Now the XML response is,
<schools>
<school>
<id>1</id>
<name>Montfort</name>
<email>montfort@gmail.com</email>
<address>12, New foundland, USA</address>
<student_count>4</student_count>
</school>
<school>
<id>2</id>
<name>Vidyashram</name>
<email>Vidyashramschool@gmaill.com</email>
<address>Chennai</address>
<student_count>0</student_count>
</school>
</schools>
Conclusion
Hope this article is helpful. Happy coding!