diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index b49ac3ed6dc..0952e190c60 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -1099,12 +1099,20 @@ def get_field_names(self, declared_fields, info): # Use the default set of field names if `Meta.fields` is not specified. fields = self.get_default_field_names(declared_fields, info) - # deduplicate field names (occurs when a declared fields matches a model field) - fields = list(OrderedDict.fromkeys(fields)) - if exclude is not None: # If `Meta.exclude` is included, then remove those fields. for field_name in exclude: + assert field_name not in self._declared_fields, ( + "Cannot both declare the field '{field_name}' and include " + "it in the {serializer_class} 'exclude' option. Remove the " + "field or, if inherited from a parent serializer, disable " + "with `{field_name} = None`." + .format( + field_name=field_name, + serializer_class=self.__class__.__name__ + ) + ) + assert field_name in fields, ( "The field '{field_name}' was included on serializer " "{serializer_class} in the 'exclude' option, but does " diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py index cea8ab5a034..98586b971dc 100644 --- a/tests/test_model_serializer.py +++ b/tests/test_model_serializer.py @@ -908,7 +908,13 @@ class Meta: model = MetaClassTestModel exclude = ('text',) - assert list(ExampleSerializer().fields) == ['id'] + expected = ( + "Cannot both declare the field 'text' and include it in the " + "ExampleSerializer 'exclude' option. Remove the field or, if " + "inherited from a parent serializer, disable with `text = None`." + ) + with self.assertRaisesMessage(AssertionError, expected): + ExampleSerializer().fields class Issue2704TestCase(TestCase):