Fixed #29078 -- Made serializers respect prefetch_related() for m2m fields.

This commit is contained in:
Claude Paroz 2020-05-24 14:14:49 +02:00 committed by Mariusz Felisiak
parent b547c42661
commit adf58311b8
3 changed files with 23 additions and 4 deletions

View File

@ -67,9 +67,11 @@ class Serializer(base.Serializer):
else: else:
def m2m_value(value): def m2m_value(value):
return self._value_from_field(value, value._meta.pk) return self._value_from_field(value, value._meta.pk)
self._current[field.name] = [ m2m_iter = getattr(obj, '_prefetched_objects_cache', {}).get(
m2m_value(related) for related in getattr(obj, field.name).iterator() field.name,
] getattr(obj, field.name).iterator(),
)
self._current[field.name] = [m2m_value(related) for related in m2m_iter]
def getvalue(self): def getvalue(self):
return self.objects return self.objects

View File

@ -132,7 +132,11 @@ class Serializer(base.Serializer):
self.xml.addQuickElement("object", attrs={ self.xml.addQuickElement("object", attrs={
'pk': str(value.pk) 'pk': str(value.pk)
}) })
for relobj in getattr(obj, field.name).iterator(): m2m_iter = getattr(obj, '_prefetched_objects_cache', {}).get(
field.name,
getattr(obj, field.name).iterator(),
)
for relobj in m2m_iter:
handle_m2m(relobj) handle_m2m(relobj)
self.xml.endElement("field") self.xml.endElement("field")

View File

@ -250,6 +250,19 @@ class SerializersTestBase:
with self.assertNumQueries(0): with self.assertNumQueries(0):
serializers.serialize(self.serializer_name, [mv]) serializers.serialize(self.serializer_name, [mv])
def test_serialize_prefetch_related_m2m(self):
# One query for the Article table and one for each prefetched m2m
# field.
with self.assertNumQueries(3):
serializers.serialize(
self.serializer_name,
Article.objects.all().prefetch_related('categories', 'meta_data'),
)
# One query for the Article table, and two m2m queries for each
# article.
with self.assertNumQueries(5):
serializers.serialize(self.serializer_name, Article.objects.all())
def test_serialize_with_null_pk(self): def test_serialize_with_null_pk(self):
""" """
Serialized data with no primary key results Serialized data with no primary key results