Merge pull request #865 from ryankask/issue-747-lazy-strings-serialized

Issue 747 lazy strings serialized
This commit is contained in:
Tom Christie 2013-05-18 09:05:42 -07:00
commit 1888f4a1f0
3 changed files with 47 additions and 5 deletions

View File

@ -495,3 +495,16 @@ except ImportError:
oauth2_provider_forms = None oauth2_provider_forms = None
oauth2_provider_scope = None oauth2_provider_scope = None
oauth2_constants = None oauth2_constants = None
# Handle lazy strings
from django.utils.functional import Promise
if six.PY3:
def is_non_str_iterable(obj):
if (isinstance(obj, str) or
(isinstance(obj, Promise) and obj._delegate_text)):
return False
return hasattr(obj, '__iter__')
else:
def is_non_str_iterable(obj):
return hasattr(obj, '__iter__')

View File

@ -26,7 +26,7 @@ from rest_framework import ISO_8601
from rest_framework.compat import timezone, parse_date, parse_datetime, parse_time from rest_framework.compat import timezone, parse_date, parse_datetime, parse_time
from rest_framework.compat import BytesIO from rest_framework.compat import BytesIO
from rest_framework.compat import six from rest_framework.compat import six
from rest_framework.compat import smart_text from rest_framework.compat import smart_text, force_text, is_non_str_iterable
from rest_framework.settings import api_settings from rest_framework.settings import api_settings
@ -45,7 +45,6 @@ def is_simple_callable(obj):
len_defaults = len(defaults) if defaults else 0 len_defaults = len(defaults) if defaults else 0
return len_args <= len_defaults return len_args <= len_defaults
def get_component(obj, attr_name): def get_component(obj, attr_name):
""" """
Given an object, and an attribute name, Given an object, and an attribute name,
@ -169,7 +168,8 @@ class Field(object):
if is_protected_type(value): if is_protected_type(value):
return value return value
elif hasattr(value, '__iter__') and not isinstance(value, (dict, six.string_types)): elif (is_non_str_iterable(value) and
not isinstance(value, (dict, six.string_types))):
return [self.to_native(item) for item in value] return [self.to_native(item) for item in value]
elif isinstance(value, dict): elif isinstance(value, dict):
# Make sure we preserve field ordering, if it exists # Make sure we preserve field ordering, if it exists
@ -177,7 +177,7 @@ class Field(object):
for key, val in value.items(): for key, val in value.items():
ret[key] = self.to_native(val) ret[key] = self.to_native(val)
return ret return ret
return smart_text(value) return force_text(value)
def attributes(self): def attributes(self):
""" """

View File

@ -1,8 +1,9 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import models from django.db import models
from django.db.models.fields import BLANK_CHOICE_DASH from django.db.models.fields import BLANK_CHOICE_DASH
from django.utils.datastructures import MultiValueDict
from django.test import TestCase from django.test import TestCase
from django.utils.datastructures import MultiValueDict
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel,
BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel, BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel,
@ -1323,6 +1324,34 @@ class DeserializeListTestCase(TestCase):
self.assertEqual(serializer.errors, expected) self.assertEqual(serializer.errors, expected)
# test for issue 747
class LazyStringModel(object):
def __init__(self, lazystring):
self.lazystring = lazystring
class LazyStringSerializer(serializers.Serializer):
lazystring = serializers.Field()
def restore_object(self, attrs, instance=None):
if instance is not None:
instance.lazystring = attrs.get('lazystring', instance.lazystring)
return instance
return LazyStringModel(**attrs)
class LazyStringsTestCase(TestCase):
def setUp(self):
self.model = LazyStringModel(lazystring=_('lazystring'))
def test_lazy_strings_are_translated(self):
serializer = LazyStringSerializer(self.model)
self.assertEqual(type(serializer.data['lazystring']),
type('lazystring'))
class AttributeMappingOnAutogeneratedFieldsTests(TestCase): class AttributeMappingOnAutogeneratedFieldsTests(TestCase):
def setUp(self): def setUp(self):