def _determine_renderer(self, request):
        """
        Determines the appropriate renderer for the output, given the client's 'Accept' header,
        and the :attr:`renderers` set on this class.

        Returns a 2-tuple of `(renderer, media_type)`

        See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
        """

        if self._ACCEPT_QUERY_PARAM and request.GET.get(
                self._ACCEPT_QUERY_PARAM, None):
            # Use _accept parameter override
            accept_list = [request.GET.get(self._ACCEPT_QUERY_PARAM)]
        elif (self._IGNORE_IE_ACCEPT_HEADER
              and 'HTTP_USER_AGENT' in request.META
              and MSIE_USER_AGENT_REGEX.match(request.META['HTTP_USER_AGENT'])
              and request.META.get('HTTP_X_REQUESTED_WITH',
                                   '') != 'XMLHttpRequest'):
            # Ignore MSIE's broken accept behavior and do something sensible instead
            accept_list = ['text/html', '*/*']
        elif 'HTTP_ACCEPT' in request.META:
            # Use standard HTTP Accept negotiation
            accept_list = [
                token.strip()
                for token in request.META['HTTP_ACCEPT'].split(',')
            ]
        else:
            # No accept header specified
            accept_list = [b'*/*']

        # Check the acceptable media types against each renderer,
        # attempting more specific media types first
        # NB. The inner loop here isn't as bad as it first looks :)
        #     Worst case is we're looping over len(accept_list) * len(self.renderers)
        renderers = [
            renderer_cls(self) for renderer_cls in self.get_renderers()
        ]

        for accepted_media_type_lst in order_by_precedence(accept_list):
            for renderer in renderers:
                for accepted_media_type in accepted_media_type_lst:
                    if renderer.can_handle_response(accepted_media_type):
                        return renderer, accepted_media_type

        # No acceptable renderers were found
        raise ErrorResponse(
            status.HTTP_406_NOT_ACCEPTABLE, {
                'detail': 'Could not satisfy the client\'s Accept header',
                'available_types': self._rendered_media_types
            })
Example #2
0
    def _determine_renderer(self, request):
        """
        Determines the appropriate renderer for the output, given the client's 'Accept' header,
        and the :attr:`renderers` set on this class.

        Returns a 2-tuple of `(renderer, media_type)`

        See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
        """

        if self._ACCEPT_QUERY_PARAM and request.GET.get(self._ACCEPT_QUERY_PARAM, None):
            # Use _accept parameter override
            accept_list = [request.GET.get(self._ACCEPT_QUERY_PARAM)]
        elif (self._IGNORE_IE_ACCEPT_HEADER and
              'HTTP_USER_AGENT' in request.META and
              MSIE_USER_AGENT_REGEX.match(request.META['HTTP_USER_AGENT']) and
              request.META.get('HTTP_X_REQUESTED_WITH', '') != 'XMLHttpRequest'):
            # Ignore MSIE's broken accept behavior and do something sensible instead
            accept_list = ['text/html', '*/*']
        elif 'HTTP_ACCEPT' in request.META:
            # Use standard HTTP Accept negotiation
            accept_list = [token.strip() for token in request.META['HTTP_ACCEPT'].split(',')]
        else:
            # No accept header specified
            accept_list = ['*/*']

        # Check the acceptable media types against each renderer,
        # attempting more specific media types first
        # NB. The inner loop here isn't as bad as it first looks :)
        #     Worst case is we're looping over len(accept_list) * len(self.renderers)
        renderers = [renderer_cls(self) for renderer_cls in self.get_renderers()]

        for accepted_media_type_lst in order_by_precedence(accept_list):
            for renderer in renderers:
                for accepted_media_type in accepted_media_type_lst:
                    if renderer.can_handle_response(accepted_media_type):
                        return renderer, accepted_media_type

        # No acceptable renderers were found
        raise ErrorResponse(status.HTTP_406_NOT_ACCEPTABLE,
                                {'detail': 'Could not satisfy the client\'s Accept header',
                                 'available_types': self._rendered_media_types})