Renderers
Renderers determine how your API responses are formatted (e.g., JSON, HTML, XML). Before a Response object is returned to the client, it must be rendered into a byte stream.
Built-in Renderers
DRF provides several built-in renderers:
JSONRenderer: Renders the response data into JSON, using utf-8 encoding. This is the standard renderer for most JSON APIs.TemplateHTMLRenderer: Renders data to HTML, using Django's standard template rendering. Useful when your API needs to serve standard HTML pages instead of pure data.StaticHTMLRenderer: Returns pre-rendered HTML without any further processing. Useful for endpoints that return pre-compiled HTML fragments.BrowsableAPIRenderer: Renders data into HTML for the browsable API. This is what powers DRF's famous self-documenting, interactive web API UI.AdminRenderer: Renders data into HTML for an admin-like interface. Suitable for CRUD-style web APIs that should also present a user-friendly interface for managing the data.MultiPartRenderer: Renders data as HTML multipart form data. This is primarily used for testing purposes, allowing you to easily simulate complex form submissions in your test suite.
Setting Renderers
By default, if you don't configure anything, DRF uses the following renderers:
[
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
]This means your API will automatically return JSON to programmatic clients, but will render the interactive Browsable API when accessed via a web browser.
You can override these globally in your settings.py:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
]
}Or on a per-view basis:
Class-Based Views
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
class UserCountView(APIView):
renderer_classes = [JSONRenderer]
def get(self, request, format=None):
user_count = User.objects.count()
return Response({'users': user_count})Function-Based Views
from rest_framework.decorators import api_view, renderer_classes
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
@api_view(['GET'])
@renderer_classes([JSONRenderer])
def user_count_view(request):
user_count = User.objects.count()
return Response({'users': user_count})Custom Renderers
To implement a custom renderer, subclass BaseRenderer, set the .media_type and .format properties and override the .render() method.
The .render() method receives the response data and must return a bytestring to be used as the HTTP response body.
Text-based Renderers
For custom text formats (like CSV or plain text), simply format your data into a string and encode it using the specified charset (which defaults to utf-8):
from rest_framework.renderers import BaseRenderer
class PlainTextRenderer(BaseRenderer):
media_type = 'text/plain'
format = 'txt'
charset = 'iso-8859-1'
def render(self, data, accepted_media_type=None, renderer_context=None):
# Format your data into a string, then encode it
text_content = str(data)
return text_content.encode(self.charset)Binary Renderers
If your renderer returns raw binary data (like an image or PDF file), set the charset to None. You should also set render_style = 'binary' so the browsable API knows not to attempt displaying the binary output as text:
from rest_framework.renderers import BaseRenderer
class JPEGRenderer(BaseRenderer):
media_type = 'image/jpeg'
format = 'jpg'
charset = None
render_style = 'binary'
def render(self, data, accepted_media_type=None, renderer_context=None):
# `data` should already be raw bytes representing the image
return dataTIP
Don't want to build your own? There are many excellent Third-Party Packages available that provide ready-to-use renderers for formats like YAML, XML, CSV, MessagePack, XLSX etc.
