XML response in Django using Django-rest-framework

Allwin Raju
3 min readDec 7, 2020

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 XMLRenderer
from 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!

--

--