[Django] #29078: Serializer handle_m2m_field should honour any previous prefetch

12 views
Skip to first unread message

Django

unread,
Jan 28, 2018, 12:20:25 PM1/28/18
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field should honour any previous prefetch
------------------------------------------------+------------------------
Reporter: xx396 | Owner: nobody
Type: Bug | Status: new
Component: Core (Serialization) | Version: 2.0
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 1
UI/UX: 0 |
------------------------------------------------+------------------------
Example:

from django.contrib.auth.models import Group
from django.core import serializers

groups = Group.objects.prefetch_related('permissions__content_type').all()
serializers.serialize('json', groups)

This will N+1 query the permissions as handle_m2m_field uses iterator()
which bypasses any cache. Suggest serializers/python.py line 77 replaces
iterator() with all()

self._current[field.name] = [
m2m_value(related) for related in getattr(obj,
field.name).iterator()
]

--
Ticket URL: <https://code.djangoproject.com/ticket/29078>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jan 28, 2018, 3:27:53 PM1/28/18
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field should honour any previous prefetch
-------------------------------------+-------------------------------------

Reporter: xx396 | Owner: nobody
Type: Bug | Status: new
Component: Core | Version: 2.0
(Serialization) |
Severity: Normal | Resolution:

Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by xx396:

Old description:

> Example:
>
> from django.contrib.auth.models import Group
> from django.core import serializers
>
> groups =
> Group.objects.prefetch_related('permissions__content_type').all()
> serializers.serialize('json', groups)
>
> This will N+1 query the permissions as handle_m2m_field uses iterator()
> which bypasses any cache. Suggest serializers/python.py line 77 replaces
> iterator() with all()
>
> self._current[field.name] = [
> m2m_value(related) for related in getattr(obj,
> field.name).iterator()
> ]

New description:

Example:

from django.contrib.auth.models import Group
from django.core import serializers

groups = Group.objects.prefetch_related('permissions').all()
serializers.serialize('json', groups)

This will N+1 query the permissions as handle_m2m_field uses iterator()
which bypasses any cache. Suggest serializers/python.py line 77 replaces
iterator() with all()

--

--
Ticket URL: <https://code.djangoproject.com/ticket/29078#comment:1>

Django

unread,
Jan 28, 2018, 3:29:13 PM1/28/18
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field should honour any previous prefetch
-------------------------------------+-------------------------------------

Reporter: xx396 | Owner: nobody
Type: Bug | Status: new
Component: Core | Version: 2.0
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by xx396:

Old description:

> Example:


>
> from django.contrib.auth.models import Group
> from django.core import serializers
>

> groups = Group.objects.prefetch_related('permissions').all()


> serializers.serialize('json', groups)
>
> This will N+1 query the permissions as handle_m2m_field uses iterator()
> which bypasses any cache. Suggest serializers/python.py line 77 replaces
> iterator() with all()

New description:

Example:

from django.contrib.auth.models import Group
from django.core import serializers

groups = Group.objects.prefetch_related('permissions').all()
serializers.serialize('json', groups)

This will N+1 query the permissions as handle_m2m_field uses iterator()

which bypasses any cache. Suggest serializers/python.py line 78 replaces
iterator() with all()

--

--
Ticket URL: <https://code.djangoproject.com/ticket/29078#comment:2>

Django

unread,
Feb 2, 2018, 6:39:11 AM2/2/18
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field should honour any previous prefetch
-------------------------------------+-------------------------------------
Reporter: xx396 | Owner: Zeeshan
| Khan
Type: Bug | Status: assigned

Component: Core | Version: 2.0
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Zeeshan Khan):

* status: new => assigned
* owner: nobody => Zeeshan Khan


--
Ticket URL: <https://code.djangoproject.com/ticket/29078#comment:3>

Django

unread,
Feb 3, 2018, 6:12:09 PM2/3/18
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field() should honor any previous prefetch

-------------------------------------+-------------------------------------
Reporter: xx396 | Owner: Zeeshan
Type: | Khan
Cleanup/optimization | Status: assigned

Component: Core | Version: 2.0
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* stage: Unreviewed => Accepted
* type: Bug => Cleanup/optimization
* easy: 1 => 0


Comment:

I guess it would be nice to fix that but removing `iterator()` negates the
memory savings on the non-prefetch case, doesn't it?

--
Ticket URL: <https://code.djangoproject.com/ticket/29078#comment:4>

Django

unread,
May 24, 2020, 8:45:56 AM5/24/20
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field() should honor any previous prefetch
-------------------------------------+-------------------------------------
Reporter: xx396 | Owner: Zeeshan
Type: | Khan
Cleanup/optimization | Status: assigned
Component: Core | Version: 2.0
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Claude Paroz):

* has_patch: 0 => 1


Comment:

I have two suggestion commits for possible fixes:
- https://github.com/claudep/django/commit/7173c7de
- https://github.com/claudep/django/commit/68bbb8ff

I can turn one of them into a PR if an ORM informed person could validate
either approach.

--
Ticket URL: <https://code.djangoproject.com/ticket/29078#comment:5>

Django

unread,
May 24, 2020, 9:29:11 AM5/24/20
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field() should honor any previous prefetch
-------------------------------------+-------------------------------------
Reporter: xx396 | Owner: Zeeshan
Type: | Khan
Cleanup/optimization | Status: assigned
Component: Core | Version: 2.0
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Simon Charette):

Claude, I think https://github.com/claudep/django/commit/7173c7de makes
more sense as the API to retrieve cached many-to-many results should
likely be added to `RelatedManager.all()` instead of `iterator`.

--
Ticket URL: <https://code.djangoproject.com/ticket/29078#comment:6>

Django

unread,
May 24, 2020, 12:18:06 PM5/24/20
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field() should honor any previous prefetch
-------------------------------------+-------------------------------------
Reporter: xx396 | Owner: Zeeshan
Type: | Khan
Cleanup/optimization | Status: assigned
Component: Core | Version: 2.0
(Serialization) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Claude Paroz):

Thanks, [https://github.com/django/django/pull/12966 PR].

--
Ticket URL: <https://code.djangoproject.com/ticket/29078#comment:7>

Django

unread,
May 25, 2020, 5:13:29 AM5/25/20
to django-...@googlegroups.com
#29078: Serializer handle_m2m_field() should honor any previous prefetch
-------------------------------------+-------------------------------------
Reporter: xx396 | Owner: Zeeshan
Type: | Khan
Cleanup/optimization | Status: closed

Component: Core | Version: 2.0
(Serialization) |
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak <felisiak.mariusz@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"adf58311b84f2aa92ca57661a8ba8679481ac930" adf58311]:
{{{
#!CommitTicketReference repository=""
revision="adf58311b84f2aa92ca57661a8ba8679481ac930"
Fixed #29078 -- Made serializers respect prefetch_related() for m2m
fields.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/29078#comment:8>

Reply all
Reply to author
Forward
0 new messages