From b53a2f74edf7402b0e10193d7496184641ba8e70 Mon Sep 17 00:00:00 2001 From: Pavel Savchenko Date: Thu, 1 Nov 2012 08:36:26 +0200 Subject: [PATCH 1/5] Do not rely that `primary_key` will always be first field, Add support for specifying `fields = ('pk',)` to serialize the primary key field (no matter how the field is actually called) --- rest_framework/serializers.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 3d134a741..9fd1a4c95 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -126,11 +126,16 @@ class BaseSerializer(Field): for key, val in fields.items(): if key not in ret: ret[key] = val + if value.source.primary_key: + pk_field = key # If 'fields' is specified, use those fields, in that order. if self.opts.fields: new = SortedDict() for key in self.opts.fields: + if key == 'pk': + # User requested the 'pk', use the primary key found + new[key] = ret[pk_field] new[key] = ret[key] ret = new @@ -344,12 +349,11 @@ class ModelSerializer(Serializer): fields += [field for field in opts.many_to_many if field.serialize] ret = SortedDict() - is_pk = True # First field in the list is the pk for model_field in fields: - if is_pk: + if model_field.primary_key: + # Django requires models to have only one primary_key so this should be safe field = self.get_pk_field(model_field) - is_pk = False elif model_field.rel and nested: field = self.get_nested_field(model_field) elif model_field.rel: From 7a127415246803ca2bf6cf073d3b9aa567841dc5 Mon Sep 17 00:00:00 2001 From: Pavel Savchenko Date: Thu, 1 Nov 2012 08:41:37 +0200 Subject: [PATCH 2/5] correct value to val --- rest_framework/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 9fd1a4c95..47c544b39 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -126,7 +126,7 @@ class BaseSerializer(Field): for key, val in fields.items(): if key not in ret: ret[key] = val - if value.source.primary_key: + if val.source.primary_key: pk_field = key # If 'fields' is specified, use those fields, in that order. From 19bcc3c86539e215e5668fac93cfc25e63166a3e Mon Sep 17 00:00:00 2001 From: Pavel Savchenko Date: Thu, 1 Nov 2012 08:51:55 +0200 Subject: [PATCH 3/5] use getattr to choose the pk field --- rest_framework/serializers.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 47c544b39..5443d2d67 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -126,8 +126,11 @@ class BaseSerializer(Field): for key, val in fields.items(): if key not in ret: ret[key] = val - if val.source.primary_key: - pk_field = key + try: + if getattr(val.source, primary_key): + pk_field = key + except AttributeError: + pass # If 'fields' is specified, use those fields, in that order. if self.opts.fields: From bd24d83333698bc8f4b923d1b45879dc9541c638 Mon Sep 17 00:00:00 2001 From: Pavel Savchenko Date: Thu, 1 Nov 2012 08:53:13 +0200 Subject: [PATCH 4/5] actually look for the right attribute --- rest_framework/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 5443d2d67..67e0cc114 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -127,7 +127,7 @@ class BaseSerializer(Field): if key not in ret: ret[key] = val try: - if getattr(val.source, primary_key): + if getattr(val.source, 'primary_key'): pk_field = key except AttributeError: pass From e01b0d9ec036d300c3091009d7bfe979380b63e1 Mon Sep 17 00:00:00 2001 From: Pavel Savchenko Date: Thu, 1 Nov 2012 08:59:19 +0200 Subject: [PATCH 5/5] Comments --- rest_framework/serializers.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 67e0cc114..8f2e315ee 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -127,7 +127,8 @@ class BaseSerializer(Field): if key not in ret: ret[key] = val try: - if getattr(val.source, 'primary_key'): + # Test if field was marked as pk_field + if getattr(val, 'is_pk_field'): pk_field = key except AttributeError: pass @@ -139,6 +140,7 @@ class BaseSerializer(Field): if key == 'pk': # User requested the 'pk', use the primary key found new[key] = ret[pk_field] + continue new[key] = ret[key] ret = new @@ -376,7 +378,10 @@ class ModelSerializer(Serializer): """ Returns a default instance of the pk field. """ - return Field() + field = Field() + # Mark field as primary key + field.is_pk_field = True + return field def get_nested_field(self, model_field): """