Support for read_only_fields on ModelSerializer classes

This commit is contained in:
Tom Christie 2012-11-09 17:01:20 +00:00
parent d365621cbe
commit e224061189
4 changed files with 37 additions and 2 deletions

View File

@ -248,6 +248,15 @@ The default `ModelSerializer` uses primary keys for relationships, but you can a
The `depth` option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation. The `depth` option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.
## Specifying which fields should be read-only
You may wish to specify multiple fields as read-only. Instead of adding each field explicitely with the `read_only=True` attribute, you may use the `read_only_fields` Meta option, like so:
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
read_only_fields = ('created', 'modified')
## Customising the default fields ## Customising the default fields
You can create customized subclasses of `ModelSerializer` that use a different set of default fields for the representation, by overriding various `get_<field_type>_field` methods. You can create customized subclasses of `ModelSerializer` that use a different set of default fields for the representation, by overriding various `get_<field_type>_field` methods.

View File

@ -4,6 +4,10 @@
> >
> &mdash; Eric S. Raymond, [The Cathedral and the Bazaar][cite]. > &mdash; Eric S. Raymond, [The Cathedral and the Bazaar][cite].
## Master
* Support for `read_only_fields` on `ModelSerializer` classes.
## 2.1.2 ## 2.1.2
**Date**: 9th Nov 2012 **Date**: 9th Nov 2012

View File

@ -321,6 +321,7 @@ class ModelSerializerOptions(SerializerOptions):
def __init__(self, meta): def __init__(self, meta):
super(ModelSerializerOptions, self).__init__(meta) super(ModelSerializerOptions, self).__init__(meta)
self.model = getattr(meta, 'model', None) self.model = getattr(meta, 'model', None)
self.read_only_fields = getattr(meta, 'read_only_fields', ())
class ModelSerializer(Serializer): class ModelSerializer(Serializer):
@ -369,6 +370,12 @@ class ModelSerializer(Serializer):
field.initialize(parent=self, field_name=model_field.name) field.initialize(parent=self, field_name=model_field.name)
ret[model_field.name] = field ret[model_field.name] = field
for field_name in self.opts.read_only_fields:
assert field_name in ret, \
"read_only_fields on '%s' included invalid item '%s'" % \
(self.__class__.__name__, field_name)
ret[field_name].read_only = True
return ret return ret
def get_pk_field(self, model_field): def get_pk_field(self, model_field):

View File

@ -51,6 +51,7 @@ class PersonSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Person model = Person
fields = ('name', 'age', 'info') fields = ('name', 'age', 'info')
read_only_fields = ('age',)
class BasicTests(TestCase): class BasicTests(TestCase):
@ -107,7 +108,8 @@ class BasicTests(TestCase):
self.assertEquals(serializer.data['sub_comment'], 'And Merry Christmas!') self.assertEquals(serializer.data['sub_comment'], 'And Merry Christmas!')
def test_model_fields_as_expected(self): def test_model_fields_as_expected(self):
""" Make sure that the fields returned are the same as defined """
Make sure that the fields returned are the same as defined
in the Meta data in the Meta data
""" """
serializer = PersonSerializer(self.person) serializer = PersonSerializer(self.person)
@ -115,12 +117,25 @@ class BasicTests(TestCase):
set(['name', 'age', 'info'])) set(['name', 'age', 'info']))
def test_field_with_dictionary(self): def test_field_with_dictionary(self):
""" Make sure that dictionaries from fields are left intact """
Make sure that dictionaries from fields are left intact
""" """
serializer = PersonSerializer(self.person) serializer = PersonSerializer(self.person)
expected = self.person_data expected = self.person_data
self.assertEquals(serializer.data['info'], expected) self.assertEquals(serializer.data['info'], expected)
def test_read_only_fields(self):
"""
Attempting to update fields set as read_only should have no effect.
"""
serializer = PersonSerializer(self.person, data={'name': 'dwight', 'age': 99})
self.assertEquals(serializer.is_valid(), True)
instance = serializer.save()
self.assertEquals(serializer.errors, {})
# Assert age is unchanged (35)
self.assertEquals(instance.age, self.person_data['age'])
class ValidationTests(TestCase): class ValidationTests(TestCase):
def setUp(self): def setUp(self):