Warn when extra_field_kwargs includes fields explicitly declared (related to #3460)

This commit is contained in:
João Ricardo Lourenço 2021-10-28 11:48:14 +01:00
parent 00cd4ef864
commit 36ab17738f
2 changed files with 39 additions and 2 deletions

View File

@ -1062,12 +1062,26 @@ class ModelSerializer(Serializer):
fields = OrderedDict() fields = OrderedDict()
for field_name in field_names: for field_name in field_names:
extra_field_kwargs = extra_kwargs.get(field_name, {})
# If the field is explicitly declared on the class then use that. # If the field is explicitly declared on the class then use that.
if field_name in declared_fields: if field_name in declared_fields:
fields[field_name] = declared_fields[field_name] assert not extra_field_kwargs, (
"The field '{field_name}' was declared on serializer "
"{serializer_class}, but has also been included in "
"extra_fields_kwargs ({extra_field_kwargs}). "
"This must be a mistake, because extra_field_kwargs are "
"not applied to declared fields. For example, if you want "
"the field to be read-only, you must explicitly pass "
"read_only=True when declaring, instead of including the "
"field in read_only_fields.".format(
field_name=field_name,
serializer_class=self.__class__.__name__,
extra_field_kwargs=extra_field_kwargs
)
)
continue continue
extra_field_kwargs = extra_kwargs.get(field_name, {})
source = extra_field_kwargs.get('source', '*') source = extra_field_kwargs.get('source', '*')
if source == '*': if source == '*':
source = field_name source = field_name

View File

@ -1333,3 +1333,26 @@ class Issue6751Test(TestCase):
serializer.save() serializer.save()
self.assertEqual(instance.char_field, 'value changed by signal') self.assertEqual(instance.char_field, 'value changed by signal')
class ExtraKwargsForDeclaredFieldsModel(models.Model):
test_field = models.CharField(max_length=64)
class TestExtraKwargsForDeclaredFields(TestCase):
"""
Passing extra_kwargs for a declared field should throw an AssertionError.
Particularly relevant for read_only_fields. See
https://github.com/encode/django-rest-framework/issues/3460.
"""
def test_extra_kwargs_for_declared_fields(self):
class TestSerializer(serializers.ModelSerializer):
test_field = serializers.CharField()
class Meta:
model = ExtraKwargsForDeclaredFieldsModel
fields = ('test_field', )
read_only_fields = ('test_field', )
with pytest.raises(AssertionError) as e_info:
TestSerializer(data={'test_field': 'abc'}).fields
assert 'extra_field_kwargs' in str(e_info.value)