mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-25 19:14:01 +03:00
Optimizations play nicely with select_related, prefetch_related
This commit is contained in:
parent
720a37d3de
commit
ca7b1f6d51
|
@ -101,17 +101,7 @@ class RelatedField(Field):
|
||||||
|
|
||||||
def get_iterable(self, instance, source_attrs):
|
def get_iterable(self, instance, source_attrs):
|
||||||
relationship = get_attribute(instance, source_attrs)
|
relationship = get_attribute(instance, source_attrs)
|
||||||
relationship = relationship.all() if (hasattr(relationship, 'all')) else relationship
|
return relationship.all() if (hasattr(relationship, 'all')) else relationship
|
||||||
|
|
||||||
if self.use_pk_only_optimization():
|
|
||||||
# Optimized case, return mock objects only containing the pk attribute.
|
|
||||||
return [
|
|
||||||
PKOnlyObject(pk=pk)
|
|
||||||
for pk in relationship.values_list('pk', flat=True)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Standard case, return the object instances.
|
|
||||||
return relationship
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def choices(self):
|
def choices(self):
|
||||||
|
|
|
@ -92,6 +92,12 @@ class HyperlinkedManyToManyTests(TestCase):
|
||||||
with self.assertNumQueries(4):
|
with self.assertNumQueries(4):
|
||||||
self.assertEqual(serializer.data, expected)
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
def test_many_to_many_retrieve_prefetch_related(self):
|
||||||
|
queryset = ManyToManySource.objects.all().prefetch_related('targets')
|
||||||
|
serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
|
||||||
|
with self.assertNumQueries(2):
|
||||||
|
serializer.data
|
||||||
|
|
||||||
def test_reverse_many_to_many_retrieve(self):
|
def test_reverse_many_to_many_retrieve(self):
|
||||||
queryset = ManyToManyTarget.objects.all()
|
queryset = ManyToManyTarget.objects.all()
|
||||||
serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
|
serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
|
||||||
|
|
|
@ -71,6 +71,12 @@ class PKManyToManyTests(TestCase):
|
||||||
with self.assertNumQueries(4):
|
with self.assertNumQueries(4):
|
||||||
self.assertEqual(serializer.data, expected)
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
def test_many_to_many_retrieve_prefetch_related(self):
|
||||||
|
queryset = ManyToManySource.objects.all().prefetch_related('targets')
|
||||||
|
serializer = ManyToManySourceSerializer(queryset, many=True)
|
||||||
|
with self.assertNumQueries(2):
|
||||||
|
serializer.data
|
||||||
|
|
||||||
def test_reverse_many_to_many_retrieve(self):
|
def test_reverse_many_to_many_retrieve(self):
|
||||||
queryset = ManyToManyTarget.objects.all()
|
queryset = ManyToManyTarget.objects.all()
|
||||||
serializer = ManyToManyTargetSerializer(queryset, many=True)
|
serializer = ManyToManyTargetSerializer(queryset, many=True)
|
||||||
|
@ -188,6 +194,12 @@ class PKForeignKeyTests(TestCase):
|
||||||
with self.assertNumQueries(3):
|
with self.assertNumQueries(3):
|
||||||
self.assertEqual(serializer.data, expected)
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
def test_reverse_foreign_key_retrieve_prefetch_related(self):
|
||||||
|
queryset = ForeignKeyTarget.objects.all().prefetch_related('sources')
|
||||||
|
serializer = ForeignKeyTargetSerializer(queryset, many=True)
|
||||||
|
with self.assertNumQueries(2):
|
||||||
|
serializer.data
|
||||||
|
|
||||||
def test_foreign_key_update(self):
|
def test_foreign_key_update(self):
|
||||||
data = {'id': 1, 'name': 'source-1', 'target': 2}
|
data = {'id': 1, 'name': 'source-1', 'target': 2}
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
|
|
|
@ -54,7 +54,14 @@ class SlugForeignKeyTests(TestCase):
|
||||||
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
|
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
|
||||||
{'id': 3, 'name': 'source-3', 'target': 'target-1'}
|
{'id': 3, 'name': 'source-3', 'target': 'target-1'}
|
||||||
]
|
]
|
||||||
self.assertEqual(serializer.data, expected)
|
with self.assertNumQueries(4):
|
||||||
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
def test_foreign_key_retrieve_select_related(self):
|
||||||
|
queryset = ForeignKeySource.objects.all().select_related('target')
|
||||||
|
serializer = ForeignKeySourceSerializer(queryset, many=True)
|
||||||
|
with self.assertNumQueries(1):
|
||||||
|
serializer.data
|
||||||
|
|
||||||
def test_reverse_foreign_key_retrieve(self):
|
def test_reverse_foreign_key_retrieve(self):
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
|
@ -65,6 +72,12 @@ class SlugForeignKeyTests(TestCase):
|
||||||
]
|
]
|
||||||
self.assertEqual(serializer.data, expected)
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
def test_reverse_foreign_key_retrieve_prefetch_related(self):
|
||||||
|
queryset = ForeignKeyTarget.objects.all().prefetch_related('sources')
|
||||||
|
serializer = ForeignKeyTargetSerializer(queryset, many=True)
|
||||||
|
with self.assertNumQueries(2):
|
||||||
|
serializer.data
|
||||||
|
|
||||||
def test_foreign_key_update(self):
|
def test_foreign_key_update(self):
|
||||||
data = {'id': 1, 'name': 'source-1', 'target': 'target-2'}
|
data = {'id': 1, 'name': 'source-1', 'target': 'target-2'}
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user