Commit a73c16b8 by Tom Christie

serializers.Field respects ordering on dicts if it exists. Closes #832

parent b950b025
...@@ -19,6 +19,7 @@ from django import forms ...@@ -19,6 +19,7 @@ from django import forms
from django.forms import widgets from django.forms import widgets
from django.utils.encoding import is_protected_type from django.utils.encoding import is_protected_type
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.datastructures import SortedDict
from rest_framework import ISO_8601 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
...@@ -170,7 +171,11 @@ class Field(object): ...@@ -170,7 +171,11 @@ class Field(object):
elif hasattr(value, '__iter__') and not isinstance(value, (dict, six.string_types)): elif hasattr(value, '__iter__') 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):
return dict(map(self.to_native, (k, v)) for k, v in value.items()) # Make sure we preserve field ordering, if it exists
ret = SortedDict()
for key, val in value.items():
ret[key] = self.to_native(val)
return ret
return smart_text(value) return smart_text(value)
def attributes(self): def attributes(self):
......
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
General serializer field tests. General serializer field tests.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
from django.utils.datastructures import SortedDict
import datetime import datetime
from decimal import Decimal from decimal import Decimal
from django.db import models from django.db import models
from django.test import TestCase from django.test import TestCase
from django.core import validators from django.core import validators
from rest_framework import serializers from rest_framework import serializers
from rest_framework.serializers import Serializer from rest_framework.serializers import Serializer
...@@ -63,6 +62,20 @@ class BasicFieldTests(TestCase): ...@@ -63,6 +62,20 @@ class BasicFieldTests(TestCase):
serializer = CharPrimaryKeyModelSerializer() serializer = CharPrimaryKeyModelSerializer()
self.assertEqual(serializer.fields['id'].read_only, False) self.assertEqual(serializer.fields['id'].read_only, False)
def test_dict_field_ordering(self):
"""
Field should preserve dictionary ordering, if it exists.
See: https://github.com/tomchristie/django-rest-framework/issues/832
"""
ret = SortedDict()
ret['c'] = 1
ret['b'] = 1
ret['a'] = 1
ret['z'] = 1
field = serializers.Field()
keys = list(field.to_native(ret).keys())
self.assertEqual(keys, ['c', 'b', 'a', 'z'])
class DateFieldTest(TestCase): class DateFieldTest(TestCase):
""" """
...@@ -645,4 +658,4 @@ class DecimalFieldTest(TestCase): ...@@ -645,4 +658,4 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '12345.6'}) s = DecimalSerializer(data={'decimal_field': '12345.6'})
self.assertFalse(s.is_valid()) self.assertFalse(s.is_valid())
self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']}) self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']})
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment