add write_only_fields option to model serializer extra kwargs

This commit is contained in:
afuenzalida 2022-05-29 17:54:54 -04:00
parent e5fb9af0ea
commit 729b6ca188
2 changed files with 59 additions and 21 deletions

View File

@ -77,6 +77,13 @@ LIST_SERIALIZER_KWARGS = (
ALL_FIELDS = '__all__'
READ_ONLY_FIELDS = 'read_only_fields'
WRITE_ONLY_FIELDS = 'write_only_fields'
EXTRA_KWARGS_FIELDS = {
READ_ONLY_FIELDS: 'read_only',
WRITE_ONLY_FIELDS: 'write_only',
}
# BaseSerializer
# --------------
@ -1373,18 +1380,19 @@ class ModelSerializer(Serializer):
"""
extra_kwargs = copy.deepcopy(getattr(self.Meta, 'extra_kwargs', {}))
read_only_fields = getattr(self.Meta, 'read_only_fields', None)
if read_only_fields is not None:
if not isinstance(read_only_fields, (list, tuple)):
raise TypeError(
'The `read_only_fields` option must be a list or tuple. '
'Got %s.' % type(read_only_fields).__name__
)
for field_name in read_only_fields:
kwargs = extra_kwargs.get(field_name, {})
kwargs['read_only'] = True
extra_kwargs[field_name] = kwargs
for option, limit in EXTRA_KWARGS_FIELDS.items():
fields = getattr(self.Meta, option, None)
if fields is not None:
if not isinstance(fields, (list, tuple)):
raise TypeError(
f'The `{option}` option must be a list or tuple. '
f'Got {type(fields).__name__}.'
)
for field_name in fields:
kwargs = extra_kwargs.get(field_name, {})
kwargs[limit] = True
extra_kwargs[field_name] = kwargs
else:
# Guard against the possible misspelling `readonly_fields` (used
# by the Django admin and others).

View File

@ -47,6 +47,11 @@ class OneFieldModel(models.Model):
char_field = models.CharField(max_length=100)
class TwoFieldModel(models.Model):
char_field = models.CharField(max_length=100)
datetime_field = models.DateTimeField()
class RegularFieldsModel(models.Model):
"""
A model class for testing regular flat fields.
@ -1078,25 +1083,29 @@ class TestMetaInheritance(TestCase):
non_model_field = serializers.CharField()
class Meta:
model = OneFieldModel
model = TwoFieldModel
read_only_fields = ('char_field', 'non_model_field')
fields = read_only_fields
write_only_fields = ('datetime_field',)
fields = read_only_fields + write_only_fields
extra_kwargs = {}
class ChildSerializer(TestSerializer):
class Meta(TestSerializer.Meta):
read_only_fields = ()
write_only_fields = ()
test_expected = dedent("""
TestSerializer():
char_field = CharField(read_only=True)
non_model_field = CharField()
datetime_field = DateTimeField(write_only=True)
""")
child_expected = dedent("""
ChildSerializer():
char_field = CharField(max_length=100)
non_model_field = CharField()
datetime_field = DateTimeField()
""")
self.assertEqual(repr(ChildSerializer()), child_expected)
self.assertEqual(repr(TestSerializer()), test_expected)
@ -1124,6 +1133,27 @@ class TestModelFieldValues(TestCase):
self.assertEqual(serializer.data, {'target': 1})
class TestExtraKwargs(TestCase):
def test_write_only_fields(self):
class TestSerializer(serializers.ModelSerializer):
class Meta:
model = OneFieldModel
write_only_fields = ('char_field',)
fields = write_only_fields
test_expected = dedent("""
TestSerializer():
char_field = CharField(max_length=100, write_only=True)
""")
self.assertEqual(repr(TestSerializer()), test_expected)
self.assertEqual(
TestSerializer().get_extra_kwargs().get('char_field', {}).get('write_only'),
True,
)
class TestUniquenessOverride(TestCase):
def test_required_not_overwritten(self):
class TestModel(models.Model):