diff options
| author | Dmitry Mukhin | 2014-08-20 20:04:48 +0400 | 
|---|---|---|
| committer | Dmitry Mukhin | 2014-08-20 20:04:48 +0400 | 
| commit | 3b07d0c9978335e183f369480618b48ff1e1b1ab (patch) | |
| tree | 041027c50d2965da1be7f93b1a6360e07ad976f9 /rest_framework/renderers.py | |
| parent | c3891b6e00daa7a92cca1c88599e046f72926bb4 (diff) | |
| parent | 59b47eac14778767a17e56bd8adc0610417f2878 (diff) | |
| download | django-rest-framework-3b07d0c9978335e183f369480618b48ff1e1b1ab.tar.bz2 | |
Merge branch 'master' into set-retry-after
Conflicts:
	tests/test_throttling.py
Diffstat (limited to 'rest_framework/renderers.py')
| -rw-r--r-- | rest_framework/renderers.py | 71 | 
1 files changed, 42 insertions, 29 deletions
| diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 7a7da561..748ebac9 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -8,7 +8,6 @@ REST framework also provides an HTML renderer the renders the browsable API.  """  from __future__ import unicode_literals -import copy  import json  import django  from django import forms @@ -16,11 +15,9 @@ from django.core.exceptions import ImproperlyConfigured  from django.http.multipartparser import parse_header  from django.template import RequestContext, loader, Template  from django.test.client import encode_multipart +from django.utils import six  from django.utils.xmlutils import SimplerXMLGenerator -from rest_framework.compat import StringIO -from rest_framework.compat import six -from rest_framework.compat import smart_text -from rest_framework.compat import yaml +from rest_framework.compat import StringIO, smart_text, yaml  from rest_framework.exceptions import ParseError  from rest_framework.settings import api_settings  from rest_framework.request import is_form_media_type, override_method @@ -54,35 +51,41 @@ class JSONRenderer(BaseRenderer):      format = 'json'      encoder_class = encoders.JSONEncoder      ensure_ascii = True -    charset = None -    # JSON is a binary encoding, that can be encoded as utf-8, utf-16 or utf-32. + +    # We don't set a charset because JSON is a binary encoding, +    # that can be encoded as utf-8, utf-16 or utf-32.      # See: http://www.ietf.org/rfc/rfc4627.txt      # Also: http://lucumr.pocoo.org/2013/7/19/application-mimetypes-and-encodings/ +    charset = None + +    def get_indent(self, accepted_media_type, renderer_context): +        if accepted_media_type: +            # If the media type looks like 'application/json; indent=4', +            # then pretty print the result. +            base_media_type, params = parse_header(accepted_media_type.encode('ascii')) +            try: +                return max(min(int(params['indent']), 8), 0) +            except (KeyError, ValueError, TypeError): +                pass + +        # If 'indent' is provided in the context, then pretty print the result. +        # E.g. If we're being called by the BrowsableAPIRenderer. +        return renderer_context.get('indent', None)      def render(self, data, accepted_media_type=None, renderer_context=None):          """ -        Render `data` into JSON. +        Render `data` into JSON, returning a bytestring.          """          if data is None:              return bytes() -        # If 'indent' is provided in the context, then pretty print the result. -        # E.g. If we're being called by the BrowsableAPIRenderer.          renderer_context = renderer_context or {} -        indent = renderer_context.get('indent', None) +        indent = self.get_indent(accepted_media_type, renderer_context) -        if accepted_media_type: -            # If the media type looks like 'application/json; indent=4', -            # then pretty print the result. -            base_media_type, params = parse_header(accepted_media_type.encode('ascii')) -            indent = params.get('indent', indent) -            try: -                indent = max(min(int(indent), 8), 0) -            except (ValueError, TypeError): -                indent = None - -        ret = json.dumps(data, cls=self.encoder_class, -            indent=indent, ensure_ascii=self.ensure_ascii) +        ret = json.dumps( +            data, cls=self.encoder_class, +            indent=indent, ensure_ascii=self.ensure_ascii +        )          # On python 2.x json.dumps() returns bytestrings if ensure_ascii=True,          # but if ensure_ascii=False, the return type is underspecified, @@ -193,6 +196,7 @@ class YAMLRenderer(BaseRenderer):      format = 'yaml'      encoder = encoders.SafeDumper      charset = 'utf-8' +    ensure_ascii = True      def render(self, data, accepted_media_type=None, renderer_context=None):          """ @@ -203,7 +207,15 @@ class YAMLRenderer(BaseRenderer):          if data is None:              return '' -        return yaml.dump(data, stream=None, encoding=self.charset, Dumper=self.encoder) +        return yaml.dump(data, stream=None, encoding=self.charset, Dumper=self.encoder, allow_unicode=not self.ensure_ascii) + + +class UnicodeYAMLRenderer(YAMLRenderer): +    """ +    Renderer which serializes to YAML. +    Does *not* apply character escaping for non-ascii characters. +    """ +    ensure_ascii = False  class TemplateHTMLRenderer(BaseRenderer): @@ -400,7 +412,7 @@ class BrowsableAPIRenderer(BaseRenderer):          """          Returns True if a form should be shown for this method.          """ -        if not method in view.allowed_methods: +        if method not in view.allowed_methods:              return  # Not a valid method          if not api_settings.FORM_METHOD_OVERRIDE: @@ -440,8 +452,10 @@ class BrowsableAPIRenderer(BaseRenderer):              if method in ('DELETE', 'OPTIONS'):                  return True  # Don't actually need to return a form -            if (not getattr(view, 'get_serializer', None) -                or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)): +            if ( +                not getattr(view, 'get_serializer', None) +                or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes) +            ):                  return              serializer = view.get_serializer(instance=obj, data=data, files=files) @@ -562,7 +576,7 @@ class BrowsableAPIRenderer(BaseRenderer):              'version': VERSION,              'breadcrumblist': self.get_breadcrumbs(request),              'allowed_methods': view.allowed_methods, -            'available_formats': [renderer.format for renderer in view.renderer_classes], +            'available_formats': [renderer_cls.format for renderer_cls in view.renderer_classes],              'response_headers': response_headers,              'put_form': self.get_rendered_html_form(view, 'PUT', request), @@ -611,4 +625,3 @@ class MultiPartRenderer(BaseRenderer):      def render(self, data, accepted_media_type=None, renderer_context=None):          return encode_multipart(self.BOUNDARY, data) - | 
