Opened 2 years ago
Last modified 2 years ago
#33950 closed Bug
ModelChoiceField and chained prefetch_related(): queries made twice — at Version 1
Reported by: | Vincent Lefoulon | Owned by: | nobody |
---|---|---|---|
Component: | Uncategorized | Version: | 3.2 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
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!