aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
authorMark Aaron Shirley2013-01-04 21:11:03 +0100
committerMark Aaron Shirley2013-01-04 21:11:03 +0100
commit213981cef394c6f7603c24b9a51096ffb56f6024 (patch)
tree356de336d49fc2552ae819009a4f0de572e8525d /rest_framework
parentad671022e1a43f91e0285f53bab64b7e33395eb3 (diff)
downloaddjango-rest-framework-213981cef394c6f7603c24b9a51096ffb56f6024.tar.bz2
Handle ObjectDoesNotExist exceptions when serializing null reverse one-to-one
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/relations.py10
-rw-r--r--rest_framework/serializers.py17
-rw-r--r--rest_framework/tests/models.py5
-rw-r--r--rest_framework/tests/relations_nested.py22
4 files changed, 44 insertions, 10 deletions
diff --git a/rest_framework/relations.py b/rest_framework/relations.py
index 686dcf04..6c1d4f5b 100644
--- a/rest_framework/relations.py
+++ b/rest_framework/relations.py
@@ -100,7 +100,10 @@ class RelatedField(WritableField):
### Regular serializer stuff...
def field_to_native(self, obj, field_name):
- value = getattr(obj, self.source or field_name)
+ try:
+ value = getattr(obj, self.source or field_name)
+ except ObjectDoesNotExist:
+ return None
return self.to_native(value)
def field_from_native(self, data, files, field_name, into):
@@ -202,7 +205,10 @@ class PrimaryKeyRelatedField(RelatedField):
pk = obj.serializable_value(self.source or field_name)
except AttributeError:
# RelatedObject (reverse relationship)
- obj = getattr(obj, self.source or field_name)
+ try:
+ obj = getattr(obj, self.source or field_name)
+ except ObjectDoesNotExist:
+ return None
return self.to_native(obj.pk)
# Forward relationship
return self.to_native(pk)
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index bd54db4c..3391a262 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -293,15 +293,18 @@ class BaseSerializer(Field):
Override default so that we can apply ModelSerializer as a nested
field to relationships.
"""
- if self.source:
- for component in self.source.split('.'):
- obj = getattr(obj, component)
+ try:
+ if self.source:
+ for component in self.source.split('.'):
+ obj = getattr(obj, component)
+ if is_simple_callable(obj):
+ obj = obj()
+ else:
+ obj = getattr(obj, field_name)
if is_simple_callable(obj):
obj = obj()
- else:
- obj = getattr(obj, field_name)
- if is_simple_callable(obj):
- obj = value()
+ except ObjectDoesNotExist:
+ return None
# If the object has an "all" method, assume it's a relationship
if is_simple_callable(getattr(obj, 'all', None)):
diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py
index 59c35074..34cdbff3 100644
--- a/rest_framework/tests/models.py
+++ b/rest_framework/tests/models.py
@@ -205,3 +205,8 @@ class NullableForeignKeySource(RESTFrameworkModel):
name = models.CharField(max_length=100)
target = models.ForeignKey(ForeignKeyTarget, null=True, blank=True,
related_name='nullable_sources')
+
+class NullableOneToOneSource(RESTFrameworkModel):
+ name = models.CharField(max_length=100)
+ target = models.OneToOneField(ForeignKeyTarget, null=True, blank=True,
+ related_name='nullable_source')
diff --git a/rest_framework/tests/relations_nested.py b/rest_framework/tests/relations_nested.py
index 5710c1ef..808399f7 100644
--- a/rest_framework/tests/relations_nested.py
+++ b/rest_framework/tests/relations_nested.py
@@ -1,7 +1,7 @@
from django.db import models
from django.test import TestCase
from rest_framework import serializers
-from rest_framework.tests.models import ForeignKeyTarget, ForeignKeySource, NullableForeignKeySource
+from rest_framework.tests.models import ForeignKeyTarget, ForeignKeySource, NullableForeignKeySource, NullableOneToOneSource
class ForeignKeySourceSerializer(serializers.ModelSerializer):
@@ -28,6 +28,13 @@ class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
model = NullableForeignKeySource
+class NullableForeignKeyTargetSerializer(serializers.ModelSerializer):
+ nullable_source = serializers.PrimaryKeyRelatedField()
+
+ class Meta:
+ model = ForeignKeyTarget
+
+
class ReverseForeignKeyTests(TestCase):
def setUp(self):
target = ForeignKeyTarget(name='target-1')
@@ -67,6 +74,10 @@ class NestedNullableForeignKeyTests(TestCase):
def setUp(self):
target = ForeignKeyTarget(name='target-1')
target.save()
+ new_target = ForeignKeyTarget(name='target-2')
+ new_target.save()
+ one_source = NullableOneToOneSource(name='one-source-1', target=target)
+ one_source.save()
for idx in range(1, 4):
if idx == 3:
target = None
@@ -82,3 +93,12 @@ class NestedNullableForeignKeyTests(TestCase):
{'id': 3, 'name': u'source-3', 'target': None},
]
self.assertEquals(serializer.data, expected)
+
+ def test_reverse_foreign_key_retrieve_with_null(self):
+ queryset = ForeignKeyTarget.objects.all()
+ serializer = NullableForeignKeyTargetSerializer(queryset)
+ expected = [
+ {'id': 1, 'name': u'target-1', 'nullable_source': 1},
+ {'id': 2, 'name': u'target-2', 'nullable_source': None},
+ ]
+ self.assertEquals(serializer.data, expected)