From c973a3b8ae6e81d9ce452c039f4816849e2551a3 Mon Sep 17 00:00:00 2001 From: Pavel Savchenko Date: Tue, 6 Nov 2012 22:04:09 +0200 Subject: [PATCH] add tests and doc changes for 'pk' #350, modify get_fields to allow excluding using 'pk' shorctut as well --- docs/api-guide/serializers.md | 2 ++ docs/tutorial/1-serialization.md | 2 +- docs/tutorial/4-authentication-and-permissions.md | 2 +- rest_framework/serializers.py | 7 ++++++- rest_framework/tests/serializer.py | 12 ++++++++++-- setup.py | 2 +- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index ee7f72dd7..c76329e50 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -236,6 +236,8 @@ For example: model = Account exclude = ('id',) +**Note**: All fields names in either `fields` or `exclude` must already be defined in the model or set explicitly, with the exception of `pk` which is a shortcut field to the actual primary key field of the model (by default Django sets this to `id` but can be overidden). + ## Specifiying nested serialization The default `ModelSerializer` uses primary keys for relationships, but you can also easily generate nested representations using the `depth` option: diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index ba64f2aa7..bdddc4d80 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -201,7 +201,7 @@ Open the file `snippets/serializers.py` again, and edit the `SnippetSerializer` class SnippetSerializer(serializers.ModelSerializer): class Meta: model = Snippet - fields = ('id', 'title', 'code', 'linenos', 'language', 'style') + fields = ('pk', 'title', 'code', 'linenos', 'language', 'style') diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index f85250bea..ba44edda4 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -59,7 +59,7 @@ Now that we've got some users to work with, we'd better add representations of t class Meta: model = User - fields = ('id', 'username', 'snippets') + fields = ('pk', 'username', 'snippets') Because `'snippets'` is a *reverse* relationship on the User model, it will not be included by default when using the `ModelSerializer` class, so we've needed to add an explicit field for it. diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 8985c8189..29aa202af 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -130,6 +130,8 @@ class BaseSerializer(Field): # Set up the field field.initialize(parent=self, field_name=key) + pk_field = None + # Add in the default fields fields = self.default_fields(nested) for key, val in fields.items(): @@ -147,7 +149,7 @@ class BaseSerializer(Field): new = SortedDict() for key in self.opts.fields: if key == 'pk': - # User requested the 'pk', use the primary key found + # 'pk' shortcut: use the primary key found new[key] = ret[pk_field] continue new[key] = ret[key] @@ -156,6 +158,9 @@ class BaseSerializer(Field): # Remove anything in 'exclude' if self.opts.exclude: for key in self.opts.exclude: + if key == 'pk': + # 'pk' shortcut: remove the primary key found + ret.pop(pk_field) ret.pop(key, None) return ret diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 8d1de4298..7b4c9f0ec 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -50,7 +50,7 @@ class PersonSerializer(serializers.ModelSerializer): class Meta: model = Person - fields = ('name', 'age', 'info') + fields = ('pk', 'name', 'age', 'info') class BasicTests(TestCase): @@ -112,7 +112,7 @@ class BasicTests(TestCase): """ serializer = PersonSerializer(self.person) self.assertEquals(set(serializer.data.keys()), - set(['name', 'age', 'info'])) + set(['pk', 'name', 'age', 'info'])) def test_field_with_dictionary(self): """ Make sure that dictionaries from fields are left intact @@ -121,6 +121,14 @@ class BasicTests(TestCase): expected = self.person_data self.assertEquals(serializer.data['info'], expected) + def test_pk_field_exists(self): + """ + Verify the `pk` shortcut for primary key (by default: `id`) + """ + + serializer = PersonSerializer(self.person) + self.assertEquals(serializer.data['pk'], self.person.id) + class ValidationTests(TestCase): def setUp(self): diff --git a/setup.py b/setup.py index 26d072837..95b4b9144 100755 --- a/setup.py +++ b/setup.py @@ -62,7 +62,7 @@ setup( author_email='tom@tomchristie.com', packages=get_packages('rest_framework'), package_data=get_package_data('rest_framework'), - test_suite='rest_framework.runtests.runtests.main', + test_suite='rest_framework.runtests.runcoverage.main', install_requires=[], classifiers=[ 'Development Status :: 4 - Beta',