From 78e572f9bf61f75512cadc879a83c0fbd09ad5ac Mon Sep 17 00:00:00 2001 From: Ben Lapid Date: Sat, 13 Apr 2013 17:06:50 +0300 Subject: [PATCH 1/3] Added BrowsableAPIUnicodeRenderer for displaying unicode data in the web interface. Added UnicodeJSONRenderer for displaying unicode data in the JSON format. --- rest_framework/renderers.py | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 4c15e0db3..401a49086 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -518,3 +518,62 @@ class BrowsableAPIRenderer(BaseRenderer): response.status_code = status.HTTP_200_OK return ret + + + +import re +all_chars = (unichr(i) for i in xrange(0x110000)) +control_chars = ''.join(map(unichr, range(0,32) + range(127,160))) +control_char_re = re.compile('[%s]' % re.escape(control_chars)) + +class BrowsableAPIUnicodeRenderer(BrowsableAPIRenderer): + def get_content(self, renderer, data, + accepted_media_type, renderer_context): + """ + Get the content as if it had been rendered by the default + non-documenting renderer. + """ + if not renderer: + return '[No renderers were found]' + + renderer_context['indent'] = 4 + content = renderer.render(data, accepted_media_type, renderer_context) + + if not not control_char_re.match(content): + return '[%d bytes of binary content]' + + return content + + +class UnicodeJSONRenderer(BaseRenderer): + """ + Renderer which serializes to json. + """ + + media_type = 'application/json' + format = 'json' + encoder_class = encoders.JSONEncoder + + def render(self, data, accepted_media_type=None, renderer_context=None): + """ + Render `obj` into json. + """ + if data is None: + return '' + + # If 'indent' is provided in the context, then pretty print the result. + # E.g. If we're being called by the BrowseableAPIRenderer. + renderer_context = renderer_context or {} + indent = renderer_context.get('indent', None) + + 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 + + return json.dumps(data, cls=self.encoder_class, indent=indent, ensure_ascii=False) From 94c9e82f4f4a8bf4de08aee362a368e55880f48c Mon Sep 17 00:00:00 2001 From: Ben Lapid Date: Sun, 14 Apr 2013 00:40:22 +0300 Subject: [PATCH 2/3] added ensure_ascii flag to JSONRenderer. UnicodeJSONRenderer now simply turns this to false --- rest_framework/renderers.py | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 401a49086..cf8a0cb1b 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -48,6 +48,7 @@ class JSONRenderer(BaseRenderer): media_type = 'application/json' format = 'json' encoder_class = encoders.JSONEncoder + ensure_ascii = True def render(self, data, accepted_media_type=None, renderer_context=None): """ @@ -71,7 +72,7 @@ class JSONRenderer(BaseRenderer): except (ValueError, TypeError): indent = None - return json.dumps(data, cls=self.encoder_class, indent=indent) + return json.dumps(data, cls=self.encoder_class, indent=indent, ensure_ascii=self.ensure_ascii) class JSONPRenderer(JSONRenderer): @@ -546,34 +547,4 @@ class BrowsableAPIUnicodeRenderer(BrowsableAPIRenderer): class UnicodeJSONRenderer(BaseRenderer): - """ - Renderer which serializes to json. - """ - - media_type = 'application/json' - format = 'json' - encoder_class = encoders.JSONEncoder - - def render(self, data, accepted_media_type=None, renderer_context=None): - """ - Render `obj` into json. - """ - if data is None: - return '' - - # If 'indent' is provided in the context, then pretty print the result. - # E.g. If we're being called by the BrowseableAPIRenderer. - renderer_context = renderer_context or {} - indent = renderer_context.get('indent', None) - - 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 - - return json.dumps(data, cls=self.encoder_class, indent=indent, ensure_ascii=False) + ensure_ascii = False From 8f4f7c3ed2d830daf42601170059df7e57513aca Mon Sep 17 00:00:00 2001 From: Ben Lapid Date: Sun, 14 Apr 2013 01:14:59 +0300 Subject: [PATCH 3/3] Removed the BrowsableAPIUnicdeRenderer class and added the control chars check into the base BrowsableAPIRenderer class --- rest_framework/renderers.py | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index cf8a0cb1b..9834c5ef8 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -26,6 +26,9 @@ from rest_framework.utils import encoders from rest_framework.utils.breadcrumbs import get_breadcrumbs from rest_framework import exceptions, parsers, status, VERSION +import re +control_chars = ''.join(map(unichr, range(0,32) + range(127,160))) +control_char_re = re.compile('[%s]' % re.escape(control_chars)) class BaseRenderer(object): """ @@ -320,7 +323,9 @@ class BrowsableAPIRenderer(BaseRenderer): renderer_context['indent'] = 4 content = renderer.render(data, accepted_media_type, renderer_context) - if not all(char in string.printable for char in content): + if type(content) == unicode and control_char_re.match(content): + return '[%d bytes of binary content]' + if type(content) == str and not all(char in string.printable for char in content): return '[%d bytes of binary content]' return content @@ -520,31 +525,5 @@ class BrowsableAPIRenderer(BaseRenderer): return ret - - -import re -all_chars = (unichr(i) for i in xrange(0x110000)) -control_chars = ''.join(map(unichr, range(0,32) + range(127,160))) -control_char_re = re.compile('[%s]' % re.escape(control_chars)) - -class BrowsableAPIUnicodeRenderer(BrowsableAPIRenderer): - def get_content(self, renderer, data, - accepted_media_type, renderer_context): - """ - Get the content as if it had been rendered by the default - non-documenting renderer. - """ - if not renderer: - return '[No renderers were found]' - - renderer_context['indent'] = 4 - content = renderer.render(data, accepted_media_type, renderer_context) - - if not not control_char_re.match(content): - return '[%d bytes of binary content]' - - return content - - class UnicodeJSONRenderer(BaseRenderer): ensure_ascii = False