diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index 5a5d8a70369..0ceb676e90a 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -67,9 +67,11 @@ class Serializer(base.Serializer): else: def m2m_value(value): return self._value_from_field(value, value._meta.pk) - self._current[field.name] = [ - m2m_value(related) for related in getattr(obj, field.name).iterator() - ] + m2m_iter = getattr(obj, '_prefetched_objects_cache', {}).get( + field.name, + getattr(obj, field.name).iterator(), + ) + self._current[field.name] = [m2m_value(related) for related in m2m_iter] def getvalue(self): return self.objects diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index 1f62c8e9711..07de9428e7f 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -132,7 +132,11 @@ class Serializer(base.Serializer): self.xml.addQuickElement("object", attrs={ '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) self.xml.endElement("field") diff --git a/tests/serializers/tests.py b/tests/serializers/tests.py index 42044b55727..439464980d4 100644 --- a/tests/serializers/tests.py +++ b/tests/serializers/tests.py @@ -250,6 +250,19 @@ class SerializersTestBase: with self.assertNumQueries(0): 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): """ Serialized data with no primary key results