mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 08:29:59 +03:00
add write_only_fields option to model serializer extra kwargs
This commit is contained in:
parent
e5fb9af0ea
commit
729b6ca188
|
@ -77,6 +77,13 @@ LIST_SERIALIZER_KWARGS = (
|
||||||
|
|
||||||
ALL_FIELDS = '__all__'
|
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
|
# BaseSerializer
|
||||||
# --------------
|
# --------------
|
||||||
|
@ -1373,26 +1380,27 @@ class ModelSerializer(Serializer):
|
||||||
"""
|
"""
|
||||||
extra_kwargs = copy.deepcopy(getattr(self.Meta, 'extra_kwargs', {}))
|
extra_kwargs = copy.deepcopy(getattr(self.Meta, 'extra_kwargs', {}))
|
||||||
|
|
||||||
read_only_fields = getattr(self.Meta, 'read_only_fields', None)
|
for option, limit in EXTRA_KWARGS_FIELDS.items():
|
||||||
if read_only_fields is not None:
|
fields = getattr(self.Meta, option, 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
|
|
||||||
|
|
||||||
else:
|
if fields is not None:
|
||||||
# Guard against the possible misspelling `readonly_fields` (used
|
if not isinstance(fields, (list, tuple)):
|
||||||
# by the Django admin and others).
|
raise TypeError(
|
||||||
assert not hasattr(self.Meta, 'readonly_fields'), (
|
f'The `{option}` option must be a list or tuple. '
|
||||||
'Serializer `%s.%s` has field `readonly_fields`; '
|
f'Got {type(fields).__name__}.'
|
||||||
'the correct spelling for the option is `read_only_fields`.' %
|
)
|
||||||
(self.__class__.__module__, self.__class__.__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).
|
||||||
|
assert not hasattr(self.Meta, 'readonly_fields'), (
|
||||||
|
'Serializer `%s.%s` has field `readonly_fields`; '
|
||||||
|
'the correct spelling for the option is `read_only_fields`.' %
|
||||||
|
(self.__class__.__module__, self.__class__.__name__)
|
||||||
|
)
|
||||||
|
|
||||||
return extra_kwargs
|
return extra_kwargs
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,11 @@ class OneFieldModel(models.Model):
|
||||||
char_field = models.CharField(max_length=100)
|
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):
|
class RegularFieldsModel(models.Model):
|
||||||
"""
|
"""
|
||||||
A model class for testing regular flat fields.
|
A model class for testing regular flat fields.
|
||||||
|
@ -1078,25 +1083,29 @@ class TestMetaInheritance(TestCase):
|
||||||
non_model_field = serializers.CharField()
|
non_model_field = serializers.CharField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = OneFieldModel
|
model = TwoFieldModel
|
||||||
read_only_fields = ('char_field', 'non_model_field')
|
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 = {}
|
extra_kwargs = {}
|
||||||
|
|
||||||
class ChildSerializer(TestSerializer):
|
class ChildSerializer(TestSerializer):
|
||||||
class Meta(TestSerializer.Meta):
|
class Meta(TestSerializer.Meta):
|
||||||
read_only_fields = ()
|
read_only_fields = ()
|
||||||
|
write_only_fields = ()
|
||||||
|
|
||||||
test_expected = dedent("""
|
test_expected = dedent("""
|
||||||
TestSerializer():
|
TestSerializer():
|
||||||
char_field = CharField(read_only=True)
|
char_field = CharField(read_only=True)
|
||||||
non_model_field = CharField()
|
non_model_field = CharField()
|
||||||
|
datetime_field = DateTimeField(write_only=True)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
child_expected = dedent("""
|
child_expected = dedent("""
|
||||||
ChildSerializer():
|
ChildSerializer():
|
||||||
char_field = CharField(max_length=100)
|
char_field = CharField(max_length=100)
|
||||||
non_model_field = CharField()
|
non_model_field = CharField()
|
||||||
|
datetime_field = DateTimeField()
|
||||||
""")
|
""")
|
||||||
self.assertEqual(repr(ChildSerializer()), child_expected)
|
self.assertEqual(repr(ChildSerializer()), child_expected)
|
||||||
self.assertEqual(repr(TestSerializer()), test_expected)
|
self.assertEqual(repr(TestSerializer()), test_expected)
|
||||||
|
@ -1124,6 +1133,27 @@ class TestModelFieldValues(TestCase):
|
||||||
self.assertEqual(serializer.data, {'target': 1})
|
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):
|
class TestUniquenessOverride(TestCase):
|
||||||
def test_required_not_overwritten(self):
|
def test_required_not_overwritten(self):
|
||||||
class TestModel(models.Model):
|
class TestModel(models.Model):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user