diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index f13c92a44..3224959e9 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -1167,9 +1167,29 @@ class ModelSerializer(Serializer): field_kwargs = get_relation_kwargs(field_name, relation_info) to_field = field_kwargs.pop('to_field', None) - if to_field and not relation_info.related_model._meta.get_field(to_field).primary_key: - field_kwargs['slug_field'] = to_field - field_class = self.serializer_related_to_field + if to_field: + def get_related_field(related_model, to_field): + '''Returns the primary key of the field defined by to_field + on the model passed in''' + from django.core.exceptions import FieldDoesNotExist + try: + return related_model._meta.get_field(to_field) + except FieldDoesNotExist: + for field in related_model._meta.fields: + if field.related_model: + try: + new_field = get_related_field( + field.related_model, to_field) + return new_field + except FieldDoesNotExist: + continue + raise FieldDoesNotExist( + '%s has not field named %r' % (related_model, to_field)) + pk = (get_related_field(relation_info.related_model, to_field) + .primary_key) + if not pk: + field_kwargs['slug_field'] = to_field + field_class = self.serializer_related_to_field # `view_name` is only valid for hyperlinked relationships. if not issubclass(field_class, HyperlinkedRelatedField): diff --git a/tests/test_onetoone_with_inheritance.py b/tests/test_onetoone_with_inheritance.py new file mode 100644 index 000000000..3b9e24dbc --- /dev/null +++ b/tests/test_onetoone_with_inheritance.py @@ -0,0 +1,44 @@ +from __future__ import unicode_literals + +from django.db import models +from django.test import TestCase + +from rest_framework import serializers +from tests.models import RESTFrameworkModel + + +# Models +from tests.test_multitable_inheritance import ChildModel + + +class ChildAssociatedModel(RESTFrameworkModel): + child_model = models.OneToOneField(ChildModel) + child_name = models.CharField(max_length=100) + + +# Serializers +class DerivedModelSerializer(serializers.ModelSerializer): + class Meta: + model = ChildModel + fields = ['id', 'name1', 'name2', 'childassociatedmodel'] + + +class ChildAssociatedModelSerializer(serializers.ModelSerializer): + + class Meta: + model = ChildAssociatedModel + fields = ['id', 'child_name'] + + +# Tests +class InheritedModelSerializationTests(TestCase): + + def test_multitable_inherited_model_fields_as_expected(self): + """ + Assert that the parent pointer field is not included in the fields + serialized fields + """ + child = ChildModel(name1='parent name', name2='child name') + serializer = DerivedModelSerializer(child) + self.assertEqual(set(serializer.data.keys()), + set(['name1', 'name2', 'id', 'childassociatedmodel']))