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": "[email protected]",
"address": "12, New foundland, USA",
"student_count": 4
},
{
"id": 2,
"name": "Vidyashram",
"email": "[email protected]",
"address": "Chennai",
"student_count": 0
}
]

This is the default JSON response.

<root>
<list-item>
<id>1</id>
<name>Montfort</name>
<email>[email protected]</email>
<address>12, New foundland, USA</address>
<student_count>4</student_count>
</list-item>
<list-item>
<id>2</id>
<name>Vidyashram</name>
<email>[email protected]</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>[email protected]</email>
<address>12, New foundland, USA</address>
<student_count>4</student_count>
</list-item>
<list-item>
<id>2</id>
<name>Vidyashram</name>
<email>[email protected]</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>[email protected]</email>
<address>12, New foundland, USA</address>
<student_count>4</student_count>
</school>
<school>
<id>2</id>
<name>Vidyashram</name>
<email>[email protected]</email>
<address>Chennai</address>
<student_count>0</student_count>
</school>
</schools>

Conclusion

Hope this article is helpful. Happy coding!

Leave a Reply

Your email address will not be published. Required fields are marked *