From a11938ce96cabc0005b9c6daa4431a7c05e4db35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryan=20O=E2=80=99Hara?= Date: Tue, 24 Apr 2018 07:15:38 -0700 Subject: [PATCH] Fixed instance being overwritten in pk-only optimization try/except block (#5747) --- rest_framework/relations.py | 4 ++-- tests/test_relations.py | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index c4e364cf2..17dc763d4 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -163,8 +163,8 @@ class RelatedField(Field): if self.use_pk_only_optimization() and self.source_attrs: # Optimized case, return a mock object only containing the pk attribute. try: - instance = get_attribute(instance, self.source_attrs[:-1]) - value = instance.serializable_value(self.source_attrs[-1]) + attribute_instance = get_attribute(instance, self.source_attrs[:-1]) + value = attribute_instance.serializable_value(self.source_attrs[-1]) if is_simple_callable(value): # Handle edge case where the relationship `source` argument # points to a `get_relationship()` method on the model diff --git a/tests/test_relations.py b/tests/test_relations.py index fd3256e89..7c4610301 100644 --- a/tests/test_relations.py +++ b/tests/test_relations.py @@ -3,7 +3,7 @@ import uuid import pytest from _pytest.monkeypatch import MonkeyPatch from django.conf.urls import url -from django.core.exceptions import ImproperlyConfigured +from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist from django.test import override_settings from django.utils.datastructures import MultiValueDict @@ -167,6 +167,22 @@ class TestHyperlinkedRelatedField(APISimpleTestCase): representation = self.field.to_representation(MockObject(pk='')) assert representation is None + def test_serialize_empty_relationship_attribute(self): + class TestSerializer(serializers.Serializer): + via_unreachable = serializers.HyperlinkedRelatedField( + source='does_not_exist.unreachable', + view_name='example', + read_only=True, + ) + + class TestSerializable: + @property + def does_not_exist(self): + raise ObjectDoesNotExist + + serializer = TestSerializer(TestSerializable()) + assert serializer.data == {'via_unreachable': None} + def test_hyperlinked_related_lookup_exists(self): instance = self.field.to_internal_value('http://example.org/example/foobar/') assert instance is self.queryset.items[0]