Skip to content

Commit

Permalink
Added a test case for PK relations and a possible fix
Browse files Browse the repository at this point in the history
  • Loading branch information
delinhabit committed Jul 25, 2015
1 parent f53c6c7 commit 16508cf
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
11 changes: 9 additions & 2 deletions rest_framework/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
from django.utils.translation import ugettext_lazy as _

from rest_framework.compat import OrderedDict
from rest_framework.fields import Field, empty, get_attribute
from rest_framework.fields import (
Field, empty, get_attribute, is_simple_callable
)
from rest_framework.reverse import reverse
from rest_framework.utils import html

Expand Down Expand Up @@ -106,7 +108,12 @@ def get_attribute(self, instance):
# Optimized case, return a mock object only containing the pk attribute.
try:
instance = get_attribute(instance, self.source_attrs[:-1])
return PKOnlyObject(pk=instance.serializable_value(self.source_attrs[-1]))

value = instance.serializable_value(self.source_attrs[-1])
if is_simple_callable(value):
value = value().pk

return PKOnlyObject(pk=value)
except AttributeError:
pass

Expand Down
28 changes: 28 additions & 0 deletions tests/test_relations_pk.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ class Meta:
fields = ('id', 'name', 'sources')


class ForeignKeyTargetCallableSourceSerializer(serializers.ModelSerializer):
class Meta:
model = ForeignKeyTarget
fields = ('id', 'name', 'first_source')

first_source = serializers.PrimaryKeyRelatedField(
read_only=True,
source='get_first_source')


class ForeignKeySourceSerializer(serializers.ModelSerializer):
class Meta:
model = ForeignKeySource
Expand Down Expand Up @@ -450,3 +460,21 @@ def test_reverse_foreign_key_retrieve_with_null(self):
{'id': 2, 'name': 'target-2', 'nullable_source': 1},
]
self.assertEqual(serializer.data, expected)


class PKRelationCallableSourceTests(TestCase):

def setUp(self):
self.target = ForeignKeyTarget.objects.create(name='target-1')
self.first_source = ForeignKeySource.objects.create(id=10, name='source-1', target=self.target)
ForeignKeySource.objects.create(name='source-2', target=self.target)

def test_relation_field_callable_source(self):
serializer = ForeignKeyTargetCallableSourceSerializer(self.target)
expected = {
'id': 1,
'name': 'target-1',
'first_source': 10,
}
with self.assertNumQueries(1):
self.assertEqual(serializer.data, expected)

0 comments on commit 16508cf

Please sign in to comment.