Browse files

[1.0.X] Fixed #9522 -- Modified handling of values in base serializer…

… so that field subclasses can define their own value_to_string() method for serialization. Thanks to Alex Koshelev for the report and initial patch.

Merge of r10554 from trunk.

git-svn-id: bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
freakboy3742 committed Apr 13, 2009
1 parent 6be2d90 commit 960d3172f630b80c909ffb517356fdb3161d2d3a
@@ -7,15 +7,15 @@
from django.conf import settings
from django.core.serializers import base
from django.db import models
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_unicode, is_protected_type
class Serializer(base.Serializer):
Serializes a QuerySet to basic Python objects.
internal_use_only = True
def start_serialization(self):
self._current = None
self.objects = []
@@ -35,7 +35,14 @@ def end_object(self, obj):
self._current = None
def handle_field(self, obj, field):
self._current[] = smart_unicode(getattr(obj,, strings_only=True)
value = field._get_val_from_obj(obj)
# Protected types (i.e., primitives like None, numbers, dates,
# and Decimals) are passed through as is. All other values are
# converted to string first.
if is_protected_type(value):
self._current[] = value
self._current[] = field.value_to_string(obj)
def handle_fk_field(self, obj, field):
related = getattr(obj,
@@ -65,11 +65,9 @@ def handle_field(self, obj, field):
"type" : field.get_internal_type()
# Get a "string version" of the object's data (this is handled by the
# serializer base class).
# Get a "string version" of the object's data.
if getattr(obj, is not None:
value = self.get_string_value(obj, field)
@@ -41,14 +41,27 @@ def smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
return s
return force_unicode(s, encoding, strings_only, errors)
def is_protected_type(obj):
"""Determine if the object instance is of a protected type.
Objects of protected types are preserved as-is when passed to
return isinstance(obj, (
int, long,
datetime.datetime,, datetime.time,
float, Decimal)
def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
Similar to smart_unicode, except that lazy instances are resolved to
strings, rather than kept as lazy objects.
If strings_only is True, don't convert (some) non-string-like objects.
if strings_only and isinstance(s, (types.NoneType, int, long, datetime.datetime,, datetime.time, float, Decimal)):
if strings_only and is_protected_type(s):
return s
if not isinstance(s, basestring,):
@@ -73,6 +73,45 @@ def __unicode__(self):
class Score(models.Model):
score = models.FloatField()
class Team(object):
def __init__(self, title):
self.title = title
def __unicode__(self):
raise NotImplementedError("Not so simple")
def __str__(self):
raise NotImplementedError("Not so simple")
def to_string(self):
return "%s" % self.title
class TeamField(models.CharField):
__metaclass__ = models.SubfieldBase
def __init__(self):
super(TeamField, self).__init__(max_length=100)
def get_db_prep_save(self, value):
return unicode(value.title)
def to_python(self, value):
if isinstance(value, Team):
return value
return Team(value)
def value_to_string(self, obj):
return self._get_val_from_obj(obj).to_string()
class Player(models.Model):
name = models.CharField(max_length=50)
rank = models.IntegerField()
team = TeamField()
def __unicode__(self):
return u'%s (%d) playing for %s' % (, self.rank,
__test__ = {'API_TESTS':"""
# Create some data:
>>> from datetime import datetime
@@ -223,6 +262,21 @@ class Score(models.Model):
>>> print list(serializers.deserialize('json', serializers.serialize('json', [sc])))[0].object.score
# Custom field with non trivial to string convertion value
>>> player = Player()
>>> = "Soslan Djanaev"
>>> player.rank = 1
>>> = Team("Spartak Moskva")
>>> serialized = serializers.serialize("json", Player.objects.all())
>>> print serialized
[{"pk": 1, "model": "serializers.player", "fields": {"name": "Soslan Djanaev", "rank": 1, "team": "Spartak Moskva"}}]
>>> obj = list(serializers.deserialize("json", serialized))[0]
>>> print obj
<DeserializedObject: Soslan Djanaev (1) playing for Spartak Moskva>
@@ -259,6 +313,20 @@ class Score(models.Model):
<DeserializedObject: Just kidding; I love TV poker>
<DeserializedObject: Time to reform copyright>
# Custom field with non trivial to string convertion value with YAML serializer
>>> print serializers.serialize("yaml", Player.objects.all())
- fields: {name: Soslan Djanaev, rank: 1, team: Spartak Moskva}
model: serializers.player
pk: 1
>>> serialized = serializers.serialize("yaml", Player.objects.all())
>>> obj = list(serializers.deserialize("yaml", serialized))[0]
>>> print obj
<DeserializedObject: Soslan Djanaev (1) playing for Spartak Moskva>
except ImportError:

0 comments on commit 960d317

Please sign in to comment.