Opened 9 years ago
Closed 8 years ago
#24975 closed New feature (fixed)
Add the ability to prefetch_related() from a model instance
Reported by: | Eduardo Klein | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
The current prefetch_related works with a queryset, so if I have, in an ecommerce site, an order with articles, I can do orders = Order.objects.prefetch_related("articles")
.
If I do now orders[0].articles.all()
, it will not query the database again.
Suppose I have an "order" and I want to prefetch the articles (I will need them several times later). If I want to prefetch them, afaik, I would need to store them in a variable in order to reuse the same articles, since every time I do order.articles.all()
it queries the db again as expected.
It's a bit inconvenient (and maybe illogical) that I can prefetch objects from a queryset (a "list" of objects), but not from the object itself.
I worked around this issue, by doing the following:
articles = order.articles.all() order._prefetched_objects_cache = {"articles": articles}
I propose to have somethins like order.prefetch("articles") that would do exactly what I did (but of course take care of verifying if _prefetched_objects_cache
already exists and any other precautions needed.
Change History (7)
comment:1 by , 9 years ago
Component: | Uncategorized → Database layer (models, ORM) |
---|---|
Description: | modified (diff) |
Version: | 1.8 → master |
comment:2 by , 9 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:3 by , 9 years ago
While a bit verbose, the following pattern also seems to work: order = Order.objects.prefetch_related('articles').get(pk=order.pk)
(I guess you may not want to reload the entire object in some cases).
comment:4 by , 9 years ago
Summary: | Prefetch_related from object directly → Add the ability to prefetch_related() from a model instance |
---|
comment:5 by , 9 years ago
You can already do the following to do the prefetch for a list of objects:
from django.db.models.query import prefetch_related_objects prefetch_related_objects([order], ['articles'])
I'm looking at making this public and documented in #25279. Then this case for prefetching for a single existing model object is just a special case of invoking prefetch_related_objects
with a list of one item.
comment:6 by , 9 years ago
That seems to work very well. Thanks for addressing this issue.
As far as I understand, this would prefetch
order.articles.all()
May be the docs could also specify how to prefetch other manager / queryset (filters).
comment:7 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Closing as a duplicate of #25279, which was fixed in 1.10, per comment 5.
Conceptually, I don't see a request not to support something like this, although I'd be curious to know why assigning the query results to an intermediate variable isn't an acceptable solution. It would be helpful if you could post to the DevelopersMailingList in order to confirm what the API should look like and make sure there's no opposition to the idea in general.