Skip to content

Commit 16508cf

Browse files
committed
Added a test case for PK relations and a possible fix
1 parent f53c6c7 commit 16508cf

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

rest_framework/relations.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
from django.utils.translation import ugettext_lazy as _
1414

1515
from rest_framework.compat import OrderedDict
16-
from rest_framework.fields import Field, empty, get_attribute
16+
from rest_framework.fields import (
17+
Field, empty, get_attribute, is_simple_callable
18+
)
1719
from rest_framework.reverse import reverse
1820
from rest_framework.utils import html
1921

@@ -106,7 +108,12 @@ def get_attribute(self, instance):
106108
# Optimized case, return a mock object only containing the pk attribute.
107109
try:
108110
instance = get_attribute(instance, self.source_attrs[:-1])
109-
return PKOnlyObject(pk=instance.serializable_value(self.source_attrs[-1]))
111+
112+
value = instance.serializable_value(self.source_attrs[-1])
113+
if is_simple_callable(value):
114+
value = value().pk
115+
116+
return PKOnlyObject(pk=value)
110117
except AttributeError:
111118
pass
112119

tests/test_relations_pk.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ class Meta:
3030
fields = ('id', 'name', 'sources')
3131

3232

33+
class ForeignKeyTargetCallableSourceSerializer(serializers.ModelSerializer):
34+
class Meta:
35+
model = ForeignKeyTarget
36+
fields = ('id', 'name', 'first_source')
37+
38+
first_source = serializers.PrimaryKeyRelatedField(
39+
read_only=True,
40+
source='get_first_source')
41+
42+
3343
class ForeignKeySourceSerializer(serializers.ModelSerializer):
3444
class Meta:
3545
model = ForeignKeySource
@@ -450,3 +460,21 @@ def test_reverse_foreign_key_retrieve_with_null(self):
450460
{'id': 2, 'name': 'target-2', 'nullable_source': 1},
451461
]
452462
self.assertEqual(serializer.data, expected)
463+
464+
465+
class PKRelationCallableSourceTests(TestCase):
466+
467+
def setUp(self):
468+
self.target = ForeignKeyTarget.objects.create(name='target-1')
469+
self.first_source = ForeignKeySource.objects.create(id=10, name='source-1', target=self.target)
470+
ForeignKeySource.objects.create(name='source-2', target=self.target)
471+
472+
def test_relation_field_callable_source(self):
473+
serializer = ForeignKeyTargetCallableSourceSerializer(self.target)
474+
expected = {
475+
'id': 1,
476+
'name': 'target-1',
477+
'first_source': 10,
478+
}
479+
with self.assertNumQueries(1):
480+
self.assertEqual(serializer.data, expected)

0 commit comments

Comments
 (0)