Click to jump to the REST-Framework column directory

Content negotiation is the process of selecting one of several possible representations to be returned to the client based on the client or server preferences.

Determine acceptable renderers

The framework uses a simple content-negotiation style that is partly client-driven and partly server-driven to determine which media types should be returned to the client, based on the available renderers, the priority of each renderer, and the client’s Accept: header.

  1. More specific media types take precedence over less specific media types
  2. If multiple media types have the same specificity, the order in which the renderers are configured for a given view takes precedence

For example, given the following Accept header:

application/json; indent=4, application/json, application/yaml, text/html, */*
Copy the code

The priority of each given media type is:

  • application/json; indent=4
  • application/json,application/yaml,text/html
  • * / *

If the requested view is configured with only YAML and HTML renderers, the framework selects either the renderer_classes first listed in the renderer_classes list or the default renderer_classes setting.

For more information on HTTP Accept headers, see RFC 2616.

The custom

It is unlikely that you want to provide a custom content negotiation scheme for the framework, but you can if you need to, and rewrite BaseContentNegotiation to implement a custom content negotiation scheme.

The framework’s content negotiation classes handle the selection of an appropriate parser for requests and an appropriate renderer for responses, so you should implement both.select_Parser (request, parsers) and.select_renderer(request, renderers, Format_suffix) method.

The select_Parser () method should return an instance of a parser from the list of available parsers, or None if None can handle the incoming request.

The select_Renderer () method should return a tuple (renderer instance, media type) or raise the NotAcceptable exception.

Here is a custom content negotiation class that ignores client requests when selecting the appropriate parser or renderer:

from rest_framework.negotiation import BaseContentNegotiation

class IgnoreClientContentNegotiation(BaseContentNegotiation) :
    def select_parser(self, request, parsers) :
        """ Select the first parser in the `.parser_classes` list. """
        return parsers[0]

    def select_renderer(self, request, renderers, format_suffix) :
        """ Select the first renderer in the `.renderer_classes` list. """
        return (renderers[0], renderers[0].media_type)
Copy the code

Setting content Negotiation

The default content negotiation class can use DEFAULT_CONTENT_NEGOTIATION_CLASS global Settings, such as the following Settings will use our sample IgnoreClientContentNegotiation class:

REST_FRAMEWORK = {
    'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'myapp.negotiation.IgnoreClientContentNegotiation',}Copy the code

You can also set up content negotiation for a single view or set of views using views based on the APIView class:

from myapp.negotiation import IgnoreClientContentNegotiation
from rest_framework.response import Response
from rest_framework.views import APIView

class NoNegotiationView(APIView) :
    """ An example view that does not perform content negotiation. """
    content_negotiation_class = IgnoreClientContentNegotiation

    def get(self, request, format=None) :
        return Response({
            'accepted media type': request.accepted_renderer.media_type
        })
Copy the code