Skip to main content
Renderers are used to serialize a response into specific media types. They give us a generic way of being able to handle various media types on the response, such as JSON encoded data or HTML output.

How the renderer is determined

The set of valid renderers for a view is always defined as a list of classes. When a view is entered, REST framework will perform content negotiation on the incoming request, and determine the most appropriate renderer to satisfy the request. The basic process of content negotiation involves examining the request’s Accept header, to determine which media types it expects in the response. Optionally, format suffixes on the URL may be used to explicitly request a particular representation (e.g., http://example.com/api/users.json). For more information see the content negotiation documentation.

Setting the renderers

The default set of renderers may be set globally, using the DEFAULT_RENDERER_CLASSES setting:
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ]
}
You can also set the renderers used for an individual view or viewset using the APIView class-based views:
from django.contrib.auth.models import User
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView

class UserCountView(APIView):
    """
    A view that returns the count of active users in JSON.
    """
    renderer_classes = [JSONRenderer]

    def get(self, request, format=None):
        user_count = User.objects.filter(active=True).count()
        content = {'user_count': user_count}
        return Response(content)
Or with the @api_view decorator:
from rest_framework.decorators import api_view, renderer_classes
from rest_framework.renderers import JSONRenderer

@api_view(['GET'])
@renderer_classes([JSONRenderer])
def user_count_view(request, format=None):
    user_count = User.objects.filter(active=True).count()
    content = {'user_count': user_count}
    return Response(content)

Ordering of renderer classes

It’s important when specifying the renderer classes for your API to think about what priority you want to assign to each media type. If a client underspecifies the representations it can accept (e.g., Accept: */*), then REST framework will select the first renderer in the list to use for the response.

Built-in Renderers

BaseRenderer

rest_framework.renderers.BaseRenderer All renderers should extend this class, setting the media_type and format attributes, and override the .render() method.

Attributes

media_type
str
default:"None"
The media type that this renderer produces (e.g., 'application/json')
format
str
default:"None"
The format string used for format suffixes (e.g., 'json')
charset
str
default:"'utf-8'"
The character encoding to use. Set to None for binary renderers
render_style
str
default:"'text'"
Either 'text' or 'binary'. Used to determine how the browsable API displays the content

Methods

render(data, accepted_media_type=None, renderer_context=None)
method
Render the response data and return a bytestring.Arguments:
  • data - The request data, as set by the Response() instantiation
  • accepted_media_type - Optional. The accepted media type, as determined by content negotiation
  • renderer_context - Optional. A dictionary of contextual information (includes view, request, response, args, kwargs by default)

JSONRenderer

rest_framework.renderers.JSONRenderer Renders the request data into JSON, using UTF-8 encoding.

Attributes

media_type
str
default:"'application/json'"
The media type produced by this renderer
format
str
default:"'json'"
The format string for format suffixes
charset
None
None because JSON is a binary encoding (utf-8, utf-16, or utf-32)
encoder_class
class
default:"encoders.JSONEncoder"
The JSON encoder class to use
ensure_ascii
bool
default:"not api_settings.UNICODE_JSON"
Whether to escape non-ASCII characters (controlled by UNICODE_JSON setting)
compact
bool
default:"api_settings.COMPACT_JSON"
Whether to use compact output (controlled by COMPACT_JSON setting)
strict
bool
default:"api_settings.STRICT_JSON"
Whether to use strict JSON encoding (controlled by STRICT_JSON setting)

Default style

Note that the default style includes unicode characters with no unnecessary whitespace:
{"unicode black star":"★","value":999}

Indented output

The client may include an 'indent' media type parameter, in which case the returned JSON will be indented:
Accept: application/json; indent=4
{
    "unicode black star": "★",
    "value": 999
}

Example

from rest_framework.renderers import JSONRenderer
from rest_framework.views import APIView

class JSONOnlyView(APIView):
    renderer_classes = [JSONRenderer]
    
    def get(self, request):
        return Response({'message': 'JSON only'})

TemplateHTMLRenderer

rest_framework.renderers.TemplateHTMLRenderer Renders data to HTML, using Django’s standard template rendering. Unlike other renderers, the data passed to the Response does not need to be serialized. Also, you may want to include a template_name argument when creating the Response.

Attributes

media_type
str
default:"'text/html'"
The media type produced by this renderer
format
str
default:"'html'"
The format string for format suffixes
charset
str
default:"'utf-8'"
The character encoding to use
template_name
str
default:"None"
The default template name to use
exception_template_names
list
Template names to try when rendering exceptions: ['%(status_code)s.html', 'api_exception.html']

Template name determination

The template name is determined by (in order of preference):
  1. An explicit template_name argument passed to the response
  2. An explicit .template_name attribute set on this class
  3. The return result of calling view.get_template_names()
When used with a view that makes use of a serializer, the Response data may not be a dictionary and will need to be wrapped before returning:
response.data = {'results': response.data}

Example

from rest_framework import generics
from rest_framework.renderers import TemplateHTMLRenderer

class UserDetail(generics.RetrieveAPIView):
    """
    A view that returns a templated HTML representation of a given user.
    """
    queryset = User.objects.all()
    renderer_classes = [TemplateHTMLRenderer]

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return Response({'user': self.object}, template_name='user_detail.html')

StaticHTMLRenderer

rest_framework.renderers.StaticHTMLRenderer A simple renderer that returns pre-rendered HTML. Unlike other renderers, the data passed to the response object should be a string representing the content to be returned.

Attributes

media_type
str
default:"'text/html'"
The media type produced by this renderer
format
str
default:"'html'"
The format string for format suffixes
charset
str
default:"'utf-8'"
The character encoding to use

Example

from rest_framework.decorators import api_view, renderer_classes
from rest_framework.renderers import StaticHTMLRenderer

@api_view(['GET'])
@renderer_classes([StaticHTMLRenderer])
def simple_html_view(request):
    data = '<html><body><h1>Hello, world</h1></body></html>'
    return Response(data)

BrowsableAPIRenderer

rest_framework.renderers.BrowsableAPIRenderer Renders data into HTML for the Browsable API. This renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page.

Attributes

media_type
str
default:"'text/html'"
The media type produced by this renderer
format
str
default:"'api'"
The format string for format suffixes
charset
str
default:"'utf-8'"
The character encoding to use
template
str
default:"'rest_framework/api.html'"
The template used to render the browsable API
filter_template
str
default:"'rest_framework/filters/base.html'"
The template used for filter forms
code_style
str
default:"'emacs'"
The Pygments code highlighting style
form_renderer_class
class
default:"HTMLFormRenderer"
The renderer class to use for rendering forms

Customizing BrowsableAPIRenderer

You can customize the behavior by overriding the get_default_renderer() method:
from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer

class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
    def get_default_renderer(self, view):
        return JSONRenderer()

AdminRenderer

rest_framework.renderers.AdminRenderer Renders data into HTML for an admin-like display. This renderer is suitable for CRUD-style web APIs that should also present a user-friendly interface for managing the data.

Attributes

media_type
str
default:"'text/html'"
The media type produced by this renderer
format
str
default:"'admin'"
The format string for format suffixes
charset
str
default:"'utf-8'"
The character encoding to use
template
str
default:"'rest_framework/admin.html'"
The template used to render the admin interface
The AdminRenderer is only able to include links to detail pages when a properly configured URL_FIELD_NAME (url by default) attribute is present in the data. For HyperlinkedModelSerializer this will be the case, but for ModelSerializer or plain Serializer classes you’ll need to include the field explicitly.

Example

class AccountSerializer(serializers.ModelSerializer):
    url = serializers.CharField(source='get_absolute_url', read_only=True)
    
    class Meta:
        model = Account

HTMLFormRenderer

rest_framework.renderers.HTMLFormRenderer Renders data returned by a serializer into an HTML form. The output does not include the enclosing <form> tags, hidden CSRF input, or submit buttons.

Attributes

media_type
str
default:"'text/html'"
The media type produced by this renderer
format
str
default:"'form'"
The format string for format suffixes
charset
str
default:"'utf-8'"
The character encoding to use
template_pack
str
default:"'rest_framework/vertical/'"
The template pack to use for rendering form fields
base_template
str
default:"'form.html'"
The base template for the form
This renderer is not intended to be used directly, but can be used in templates by passing a serializer instance to the render_form template tag.

Example

{% load rest_framework %}

<form action="/submit-report/" method="post">
    {% csrf_token %}
    {% render_form serializer %}
    <input type="submit" value="Save" />
</form>

MultiPartRenderer

rest_framework.renderers.MultiPartRenderer This renderer is used for rendering HTML multipart form data. It is not suitable as a response renderer, but is instead used for creating test requests.

Attributes

media_type
str
default:"'multipart/form-data; boundary=BoUnDaRyStRiNg'"
The media type produced by this renderer
format
str
default:"'multipart'"
The format string for format suffixes
charset
str
default:"'utf-8'"
The character encoding to use

OpenAPIRenderer

rest_framework.renderers.OpenAPIRenderer Renders OpenAPI schema to YAML format.

Attributes

media_type
str
default:"'application/vnd.oai.openapi'"
The media type produced by this renderer
format
str
default:"'openapi'"
The format string for format suffixes
charset
None
None for binary output

JSONOpenAPIRenderer

rest_framework.renderers.JSONOpenAPIRenderer Renders OpenAPI schema to JSON format.

Attributes

media_type
str
default:"'application/vnd.oai.openapi+json'"
The media type produced by this renderer
format
str
default:"'openapi-json'"
The format string for format suffixes
charset
None
None for binary output
encoder_class
class
default:"encoders.JSONEncoder"
The JSON encoder class to use
ensure_ascii
bool
default:"not api_settings.UNICODE_JSON"
Whether to escape non-ASCII characters

Custom Renderers

To implement a custom renderer, you should override BaseRenderer, set the .media_type and .format properties, and implement the .render(self, data, accepted_media_type=None, renderer_context=None) method. The method should return a bytestring, which will be used as the body of the HTTP response.

Arguments

data
any
The request data, as set by the Response() instantiation
accepted_media_type
str
Optional. If provided, this is the accepted media type, as determined by the content negotiation stage. May include media type parameters (e.g., "application/json; nested=true").
renderer_context
dict
Optional. A dictionary of contextual information provided by the view. By default includes: view, request, response, args, kwargs.

Example

The following is an example plaintext renderer:
from django.utils.encoding import smart_str
from rest_framework import renderers

class PlainTextRenderer(renderers.BaseRenderer):
    media_type = 'text/plain'
    format = 'txt'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return smart_str(data, encoding=self.charset)

Setting the character set

By default renderer classes use UTF-8 encoding. To use a different encoding, set the charset attribute:
class PlainTextRenderer(renderers.BaseRenderer):
    media_type = 'text/plain'
    format = 'txt'
    charset = 'iso-8859-1'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return data.encode(self.charset)

Binary renderers

If the renderer returns raw binary content, set charset to None and optionally set render_style to 'binary':
class JPEGRenderer(renderers.BaseRenderer):
    media_type = 'image/jpeg'
    format = 'jpg'
    charset = None
    render_style = 'binary'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return data

Advanced Renderer Usage

Varying behavior by media type

You can access request.accepted_renderer to determine the negotiated renderer:
from rest_framework.decorators import api_view, renderer_classes
from rest_framework.renderers import TemplateHTMLRenderer, JSONRenderer

@api_view(['GET'])
@renderer_classes([TemplateHTMLRenderer, JSONRenderer])
def list_users(request):
    """
    A view that can return JSON or HTML representations.
    """
    queryset = User.objects.filter(active=True)

    if request.accepted_renderer.format == 'html':
        # TemplateHTMLRenderer takes a context dict
        data = {'users': queryset}
        return Response(data, template_name='list_users.html')

    # JSONRenderer requires serialized data
    serializer = UserSerializer(instance=queryset, many=True)
    data = serializer.data
    return Response(data)

Underspecifying the media type

You can use wildcard media types like image/* or */*. Make sure to specify the media type explicitly when returning the response:
return Response(data, content_type='image/png')

Third-party Renderers

YAML

REST framework YAML provides YAML parsing and rendering support.
pip install djangorestframework-yaml
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_yaml.renderers.YAMLRenderer',
    ],
}

XML

REST Framework XML provides a simple informal XML format.
pip install djangorestframework-xml
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_xml.renderers.XMLRenderer',
    ],
}

JSONP

REST framework JSONP provides JSONP rendering support.
If you require cross-domain AJAX requests, you should generally use the more modern approach of CORS as an alternative to JSONP. The jsonp approach is a browser hack and is only appropriate for globally readable API endpoints where GET requests are unauthenticated.

CSV

djangorestframework-csv provides CSV renderer support for tabular data that can be imported into spreadsheet applications.

Excel (XLSX)

drf-excel renders endpoints as XLSX spreadsheets using OpenPyXL, allowing clients to download formatted Excel files.
pip install drf-excel
from rest_framework.viewsets import ReadOnlyModelViewSet
from drf_excel.mixins import XLSXFileMixin
from drf_excel.renderers import XLSXRenderer

class MyExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
    queryset = MyExampleModel.objects.all()
    serializer_class = MyExampleSerializer
    renderer_classes = [XLSXRenderer]
    filename = 'my_export.xlsx'

MessagePack

MessagePack is a fast, efficient binary serialization format. The djangorestframework-msgpack package provides MessagePack renderer and parser support.

CamelCase JSON

djangorestframework-camel-case provides camel case JSON renderers and parsers, allowing serializers to use Python-style underscored field names while exposing Javascript-style camel case field names in the API.

UltraJSON

drf_ujson2 is a fork that implements JSON rendering using the optimized UltraJSON package for significantly faster JSON rendering.

LaTeX

Rest Framework Latex provides a renderer that outputs PDFs using Lualatex.

Build docs developers (and LLMs) love