[Django] #33950: ModelChoiceField and chained prefetch_related(): queries made twice

8 views
Skip to first unread message

Django

unread,
Aug 23, 2022, 6:06:53 AM8/23/22
to django-...@googlegroups.com
#33950: ModelChoiceField and chained prefetch_related(): queries made twice
--------------------------------------------+------------------------
Reporter: Vincent Lefoulon | Owner: nobody
Type: Bug | Status: new
Component: Uncategorized | Version: 3.2
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------------+------------------------
Hi!

I have these three models:

```
class Place(models.Model):
name = models.CharField(max_length=255)

class Visit(models.Model):
date = models.DateField()
place = models.ForeignKey(Place, on_delete=models.CASCADE,
related_name="visits")

class VisitDocument(models.Model):
visit = models.ForeignKey(Visit, on_delete=models.CASCADE,
related_name="documents")
file = models.FileField()
```

A form to edit a visit:

```
class VisitForm(forms.ModelForm):
class Meta:
model = Visit
exclude = ("place",)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.fields["documents_to_delete"] =
forms.ModelMultipleChoiceField(
queryset=self.instance.documents.all(),
required=False,
)
```

And a generic view for the places:

```
class PlaceView(DetailView):
queryset = Place.objects.prefetch_related("visits__documents")

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if "visit_form" not in context:
context["visit_forms"] = [
VisitForm(instance=visit)
for visit in self.object.visits.all()
]

def post(self, request, *args, **kwargs):
// Handle the form
```

Despite the `prefetch_related("visits__documents")` call in my view,
`ModelMultipleChoiceField()` doesn't detect that the documents of the
visit (i.e. the form instance) are already fetched because
`visit.documents.all()._prefetch_related_lookups` is null:
https://github.com/django/django/blob/stable/3.2.x/django/forms/models.py#L1167

So is in the view: `self.object.visits.all()._prefetch_related_lookups` is
null as well.

Many thanks!

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

Django

unread,
Aug 23, 2022, 6:08:25 AM8/23/22
to django-...@googlegroups.com
#33950: ModelChoiceField and chained prefetch_related(): queries made twice
----------------------------------+--------------------------------------

Reporter: Vincent Lefoulon | Owner: nobody
Type: Bug | Status: new
Component: Uncategorized | Version: 3.2
Severity: Normal | Resolution:

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

Old description:

New description:

Hi!

Many thanks!

--

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

Django

unread,
Aug 23, 2022, 6:10:30 AM8/23/22
to django-...@googlegroups.com

Old description:

New description:

Hi!

if "visit_forms" not in context:


context["visit_forms"] = [
VisitForm(instance=visit)
for visit in self.object.visits.all()
]

def post(self, request, *args, **kwargs):
// Handle the form
}}}

Despite the {{{prefetch_related("visits__documents")}}} call in my view,
{{{ModelMultipleChoiceField()}}} doesn't detect that the documents of the
visit (i.e. the form instance) are already fetched because
{{{visit.documents.all()._prefetch_related_lookups}}} is null:
https://github.com/django/django/blob/stable/3.2.x/django/forms/models.py#L1167

So is in the view:
{{{self.object.visits.all()._prefetch_related_lookups}}} is null as well.

Then the queries are made twice, erasing the {{{prefetch_related()}}}
effect.

Many thanks!

--

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

Django

unread,
Aug 23, 2022, 6:34:49 AM8/23/22
to django-...@googlegroups.com
#33950: ModelChoiceField and chained prefetch_related(): queries made twice
----------------------------------+--------------------------------------
Reporter: Vincent Lefoulon | Owner: nobody
Type: Bug | Status: closed
Component: Uncategorized | Version: 3.2
Severity: Normal | Resolution: duplicate

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------+--------------------------------------
Changes (by Carlton Gibson):

* status: new => closed
* resolution: => duplicate


Comment:

Duplicate of #22841.

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

Reply all
Reply to author
Forward
0 new messages