#26676 closed Bug (fixed)
Prefetch with to_attr shouldn't store its result in the referenced relation cache
Reported by: | Arnaud B | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.10 |
Severity: | Release blocker | Keywords: | Prefetch prefetch_related queryset |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When using prefetch_related with a Prefetch whose to_attr is set, the related object returns a list instead of a queryset, making chaining queries impossible. This bug affects both version 1.9 and 1.10, but to a different extent.
This minimal example illustrates the issue, the test fails with AttributeError: 'list' object has no attribute 'filter'
model'
from django.db import models class Book(models.Model): name = models.CharField(max_length=12) class Page(models.Model): number = models.SmallIntegerField() text = models.TextField() book = models.ForeignKey(Book)
tests.py
from django.test import TestCase from alpha_test.models import Book, Page from django.db.models import Q, Prefetch class SimpleCase(TestCase): def setUp(self): book = Book.objects.create(name="Django Textbook") page1 = Page.objects.create(number=1, text="lorem", book=book) page2 = Page.objects.create(number=2, text="ipsum", book=book) def test_prefech_related_with_Prefetch(self): queryset = Page.objects.filter(number=1) prefetch_no_attr = Prefetch('page_set', queryset=queryset) prefetch_with_attr = Prefetch('page_set', queryset=queryset, to_attr='first_page') # Selecting the book with the Prefetch without to_attr # it is possible to chain queries on the page_set book = Book.objects.prefetch_related(prefetch_no_attr).first() first_page = book.page_set.filter(number=1) # works fine # Now with Prefetch with to_attr set to some value, # the same query on page_set fails for 1.10 (but works for 1.9). book = Book.objects.prefetch_related(prefetch_with_attr).first() first_page = book.page_set.filter(number=1) # However, querying on the to_attr fails for both 1.9 and 1.10 first_page = book.first_page.filter(text="lorem")
Change History (5)
comment:1 by , 8 years ago
Severity: | Normal → Release blocker |
---|---|
Summary: | prefetch_related incorrectly returns list instead of queryset when using Prefetch with to_attr → Prefetch with to_attr shouldn't store its result in the referenced relation cache |
Triage Stage: | Unreviewed → Accepted |
Version: | master → 1.10 |
comment:3 by , 8 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Note:
See TracTickets
for help on using tickets.
Hi Ursidours,
Thanks for your very detailed report.
As documented, when using
to_attr
the prefetched result is stored in a list. If you'd like to request this to be changed I suggest you open a new ticket for this purpose.Now, using
to_attr
shouldn't prefetch and store results for the referenced relation (unless the referenced relation equalsto_attr
). It should be left untouched and that's a regression in 1.10 introduced by bdbe50a491ca41e7d4ebace47bfe8abe50a58211.Based on your model definition a simplified test case could look like: