mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-02 19:40:13 +03:00
Merge 7dec01d174
into 6f8acb5a76
This commit is contained in:
commit
d3e9159fe7
|
@ -109,11 +109,29 @@ def _get_declared_fields(bases, attrs):
|
||||||
# If this class is subclassing another Serializer, add that Serializer's
|
# If this class is subclassing another Serializer, add that Serializer's
|
||||||
# fields. Note that we loop over the bases in *reverse*. This is necessary
|
# fields. Note that we loop over the bases in *reverse*. This is necessary
|
||||||
# in order to maintain the correct order of fields.
|
# in order to maintain the correct order of fields.
|
||||||
|
# Note: The 'seen' dict here ensures that the fields from the 'first' base
|
||||||
|
# take precedence over fields from later bases.
|
||||||
|
# (otherwise SortedDict will squash the first-base field and
|
||||||
|
# use the field from a later base instead.)
|
||||||
|
seen = set()
|
||||||
|
base_fields_map = {}
|
||||||
|
base_fields_order = []
|
||||||
for base in bases[::-1]:
|
for base in bases[::-1]:
|
||||||
if hasattr(base, 'base_fields'):
|
if hasattr(base, 'base_fields'):
|
||||||
fields = list(base.base_fields.items()) + fields
|
for name, field in base.base_fields.items():
|
||||||
|
base_fields_map[name] = field
|
||||||
|
base_fields_order = list(base.base_fields.keys()) + base_fields_order
|
||||||
|
|
||||||
return SortedDict(fields)
|
seen = set()
|
||||||
|
base_fields = []
|
||||||
|
for name in base_fields_order:
|
||||||
|
if name not in seen:
|
||||||
|
base_fields.append((name, base_fields_map[name]))
|
||||||
|
seen.add(name)
|
||||||
|
|
||||||
|
# if there are fields in both base_fields and fields, SortedDict
|
||||||
|
# uses the *last* one defined. So fields needs to go last.
|
||||||
|
return SortedDict(base_fields + fields)
|
||||||
|
|
||||||
|
|
||||||
class SerializerMetaclass(type):
|
class SerializerMetaclass(type):
|
||||||
|
|
|
@ -1643,3 +1643,72 @@ class SerializerSupportsManyRelationships(TestCase):
|
||||||
serializer = SimpleSlugSourceModelSerializer(data={'text': 'foo', 'targets': [1, 2]})
|
serializer = SimpleSlugSourceModelSerializer(data={'text': 'foo', 'targets': [1, 2]})
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
self.assertEqual(serializer.data, {'text': 'foo', 'targets': [1, 2]})
|
self.assertEqual(serializer.data, {'text': 'foo', 'targets': [1, 2]})
|
||||||
|
|
||||||
|
|
||||||
|
### Regression test for #1053
|
||||||
|
|
||||||
|
class OverriddenFieldsBase1(serializers.Serializer):
|
||||||
|
a_field = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
class OverriddenFieldsBase2(serializers.Serializer):
|
||||||
|
a_field = serializers.IntegerField()
|
||||||
|
|
||||||
|
|
||||||
|
class OverriddenFieldsWithSingleBase(OverriddenFieldsBase1):
|
||||||
|
a_field = serializers.FloatField()
|
||||||
|
|
||||||
|
|
||||||
|
class OverriddenFieldsMultipleBases1(OverriddenFieldsBase1, OverriddenFieldsBase2):
|
||||||
|
# first base takes precedence; a_field should be a CharField.
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OverriddenFieldsMultipleBases2(OverriddenFieldsBase2, OverriddenFieldsBase1):
|
||||||
|
# first base takes precedence; a_field should be a IntegerField.
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OverriddenFieldsMultipleBasesOverridden(OverriddenFieldsBase1, OverriddenFieldsBase2):
|
||||||
|
a_field = serializers.FloatField()
|
||||||
|
|
||||||
|
|
||||||
|
class SerializerSupportsOverriddenFields(TestCase):
|
||||||
|
def test_base_fields_unchanged(self):
|
||||||
|
self.assertIsInstance(
|
||||||
|
OverriddenFieldsBase1.base_fields['a_field'],
|
||||||
|
serializers.CharField,
|
||||||
|
)
|
||||||
|
s = OverriddenFieldsBase1()
|
||||||
|
self.assertIsInstance(s.fields['a_field'], serializers.CharField)
|
||||||
|
|
||||||
|
def test_overridden_fields_single_base(self):
|
||||||
|
self.assertIsInstance(
|
||||||
|
OverriddenFieldsWithSingleBase.base_fields['a_field'],
|
||||||
|
serializers.FloatField,
|
||||||
|
)
|
||||||
|
s = OverriddenFieldsWithSingleBase()
|
||||||
|
self.assertIsInstance(s.fields['a_field'], serializers.FloatField)
|
||||||
|
|
||||||
|
def test_overridden_fields_multiple_bases(self):
|
||||||
|
self.assertIsInstance(
|
||||||
|
OverriddenFieldsMultipleBases1.base_fields['a_field'],
|
||||||
|
serializers.CharField,
|
||||||
|
)
|
||||||
|
s = OverriddenFieldsMultipleBases1()
|
||||||
|
self.assertIsInstance(s.fields['a_field'], serializers.CharField)
|
||||||
|
|
||||||
|
self.assertIsInstance(
|
||||||
|
OverriddenFieldsMultipleBases2.base_fields['a_field'],
|
||||||
|
serializers.IntegerField,
|
||||||
|
)
|
||||||
|
s = OverriddenFieldsMultipleBases2()
|
||||||
|
self.assertIsInstance(s.fields['a_field'], serializers.IntegerField)
|
||||||
|
|
||||||
|
def test_overridden_fields_multiple_bases_overridden(self):
|
||||||
|
self.assertIsInstance(
|
||||||
|
OverriddenFieldsMultipleBasesOverridden.base_fields['a_field'],
|
||||||
|
serializers.FloatField,
|
||||||
|
)
|
||||||
|
s = OverriddenFieldsMultipleBasesOverridden()
|
||||||
|
self.assertIsInstance(s.fields['a_field'], serializers.FloatField)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user