diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index c88b9b0c6..930e6e01a 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -233,6 +233,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. +## Specifying which fields should be read_only in bulk + +You may wish to specify multiple fields as "read_only" which effectively ignores these fields when they appear in an "unsafe" request. Instead of adding each field explicitely with the `read_only=True` attribute, you may use the `read_only` Meta option, like so: + + class MySerializer(serializers.ModelSerializer): + class Meta: + model = Fruit + read_only = ("color", "texture", "flavor", "family",) + ## 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` methods. diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 0db06d150..3513cacfe 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -73,7 +73,7 @@ class SerializerOptions(object): self.depth = getattr(meta, 'depth', 0) self.fields = getattr(meta, 'fields', ()) self.exclude = getattr(meta, 'exclude', ()) - self.read_only_fields = getattr(meta, 'read_only_fields', ()) + self.read_only = getattr(meta, 'read_only', ()) class BaseSerializer(Field): @@ -125,7 +125,7 @@ class BaseSerializer(Field): # Add in the default fields fields = self.default_fields(serialize, obj, data, nested) for key, val in fields.items(): - if key in self.opts.read_only_fields: + if key in self.opts.read_only: val.read_only = True if key not in ret: diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 3fd490644..21a188e0e 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -51,6 +51,7 @@ class PersonSerializer(serializers.ModelSerializer): class Meta: model = Person fields = ('name', 'age', 'info') + read_only = ('age',) class BasicTests(TestCase): @@ -105,7 +106,7 @@ class BasicTests(TestCase): self.assertEquals(serializer.object, expected) self.assertTrue(serializer.object is expected) self.assertEquals(serializer.data['sub_comment'], 'And Merry Christmas!') - + def test_model_fields_as_expected(self): """ Make sure that the fields returned are the same as defined in the Meta data @@ -121,6 +122,18 @@ class BasicTests(TestCase): expected = self.person_data 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({'name': 'dwight', 'age': 99}, instance=self.person) + 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): def setUp(self): @@ -220,6 +233,7 @@ class ValidationTests(TestCase): """ Omitting a value for null-field should validate. """ + serializer = PersonSerializer({'name': 'marko'}) self.assertEquals(serializer.is_valid(), True) self.assertEquals(serializer.errors, {})