diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 33da0bad0..b28c06586 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -20,7 +20,7 @@ from collections import Mapping, OrderedDict from django.core.exceptions import ValidationError as DjangoValidationError from django.core.exceptions import ImproperlyConfigured from django.db import models -from django.db.models import DurationField as ModelDurationField +from django.db.models import manager, DurationField as ModelDurationField from django.db.models.fields import Field as DjangoModelField from django.db.models.fields import FieldDoesNotExist from django.utils import six, timezone @@ -654,7 +654,7 @@ class ListSerializer(BaseSerializer): """ # Dealing with nested relationships, data can be a Manager, # so, first get a queryset from the Manager if needed - iterable = data.all() if isinstance(data, models.Manager) else data + iterable = data.all() if isinstance(data, manager.BaseManager) else data return [ self.child.to_representation(item) for item in iterable diff --git a/tests/models.py b/tests/models.py index e5d49a0a5..40f69031f 100644 --- a/tests/models.py +++ b/tests/models.py @@ -3,6 +3,8 @@ from __future__ import unicode_literals import uuid from django.db import models +from django.db.models.manager import BaseManager +from django.db.models.query import QuerySet from django.utils.translation import ugettext_lazy as _ @@ -45,12 +47,18 @@ class UUIDForeignKeyTarget(RESTFrameworkModel): name = models.CharField(max_length=100) +class ForeignKeySourceManager(BaseManager.from_queryset(QuerySet)): + pass + + class ForeignKeySource(RESTFrameworkModel): name = models.CharField(max_length=100) target = models.ForeignKey(ForeignKeyTarget, related_name='sources', help_text='Target', verbose_name='Target', on_delete=models.CASCADE) + objects = ForeignKeySourceManager() + # Nullable ForeignKey class NullableForeignKeySource(RESTFrameworkModel): diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py index 3317d6251..5eb031c36 100644 --- a/tests/test_relations_pk.py +++ b/tests/test_relations_pk.py @@ -26,16 +26,24 @@ class ManyToManySourceSerializer(serializers.ModelSerializer): # ForeignKey +class ForeignKeySourceSerializer(serializers.ModelSerializer): + class Meta: + model = ForeignKeySource + fields = ('id', 'name', 'target') + + class ForeignKeyTargetSerializer(serializers.ModelSerializer): class Meta: model = ForeignKeyTarget fields = ('id', 'name', 'sources') -class ForeignKeySourceSerializer(serializers.ModelSerializer): +class ForeignKeyTargetWithSourcesSerializer(serializers.ModelSerializer): + sources = ForeignKeySourceSerializer(many=True) + class Meta: - model = ForeignKeySource - fields = ('id', 'name', 'target') + model = ForeignKeyTarget + fields = ('id', 'name', 'sources') # Nullable ForeignKey @@ -219,9 +227,13 @@ class PKForeignKeyTests(TestCase): def test_reverse_foreign_key_retrieve(self): queryset = ForeignKeyTarget.objects.all() - serializer = ForeignKeyTargetSerializer(queryset, many=True) + serializer = ForeignKeyTargetWithSourcesSerializer(queryset, many=True) expected = [ - {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]}, + {'id': 1, 'name': 'target-1', 'sources': [ + {'id': 1, 'name': 'source-1', 'target': 1}, + {'id': 2, 'name': 'source-2', 'target': 1}, + {'id': 3, 'name': 'source-3', 'target': 1}, + ]}, {'id': 2, 'name': 'target-2', 'sources': []}, ] with self.assertNumQueries(3): @@ -229,7 +241,7 @@ class PKForeignKeyTests(TestCase): def test_reverse_foreign_key_retrieve_prefetch_related(self): queryset = ForeignKeyTarget.objects.all().prefetch_related('sources') - serializer = ForeignKeyTargetSerializer(queryset, many=True) + serializer = ForeignKeyTargetWithSourcesSerializer(queryset, many=True) with self.assertNumQueries(2): serializer.data