From d365621cbeb333d857dd312147edd5cd076866e8 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 9 Nov 2012 16:44:39 +0000 Subject: [PATCH 1/2] Note django-filter installation --- docs/index.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index 1874ec00b..fd8345402 100644 --- a/docs/index.md +++ b/docs/index.md @@ -32,7 +32,7 @@ REST framework requires the following: The following packages are optional: -* [Markdown][markdown] (2.1.0+) - Markdown support for the self describing API. +* [Markdown][markdown] (2.1.0+) - Markdown support for the browseable API. * [PyYAML][yaml] (3.10+) - YAML content-type support. * [django-filter][django-filter] (master) - Filtering support. @@ -41,8 +41,9 @@ The following packages are optional: Install using `pip`, including any optional packages you want... pip install djangorestframework - pip install markdown # Recommended if using the browseable API. - pip install pyyaml # Required for yaml content-type support. + pip install markdown # Markdown support for the browseable API. + pip install pyyaml # YAML content-type support. + pip install -e git+https://github.com/alex/django-filter.git#egg=django-filter # Filtering support ...or clone the project from github. From e224061189a6a5ea2c063f3820239eed6c3a88fb Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 9 Nov 2012 17:01:20 +0000 Subject: [PATCH 2/2] Support for `read_only_fields` on `ModelSerializer` classes --- docs/api-guide/serializers.md | 9 +++++++++ docs/topics/release-notes.md | 4 ++++ rest_framework/serializers.py | 7 +++++++ rest_framework/tests/serializer.py | 19 +++++++++++++++++-- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 0cdae1ce3..a95891449 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -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. +## 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 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/docs/topics/release-notes.md b/docs/topics/release-notes.md index 670332e60..35e8a8b35 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -4,6 +4,10 @@ > > — Eric S. Raymond, [The Cathedral and the Bazaar][cite]. +## Master + +* Support for `read_only_fields` on `ModelSerializer` classes. + ## 2.1.2 **Date**: 9th Nov 2012 diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 95145d580..329b38f2d 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -321,6 +321,7 @@ class ModelSerializerOptions(SerializerOptions): def __init__(self, meta): super(ModelSerializerOptions, self).__init__(meta) self.model = getattr(meta, 'model', None) + self.read_only_fields = getattr(meta, 'read_only_fields', ()) class ModelSerializer(Serializer): @@ -369,6 +370,12 @@ class ModelSerializer(Serializer): field.initialize(parent=self, field_name=model_field.name) 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 def get_pk_field(self, model_field): diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 8d1de4298..059593a90 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_fields = ('age',) class BasicTests(TestCase): @@ -107,7 +108,8 @@ class BasicTests(TestCase): 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 + """ + Make sure that the fields returned are the same as defined in the Meta data """ serializer = PersonSerializer(self.person) @@ -115,12 +117,25 @@ class BasicTests(TestCase): set(['name', 'age', 'info'])) 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) 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(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): def setUp(self):