#26226: prefetch_related with Prefetch with queryset with explicit Ordering
Ignored
- single order_by
-------------------------------------+-------------------------------------
Reporter: cancan101 | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) |
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
-------------------------------------+-------------------------------------
Comment (by charettes):
I'm not sure this worth fixing but here's why `ordered=False` and how we
could fix this.
When using `prefetch_related()` without `to_attr` the prefetched results
are stored in the cached results of a `QuerySet` instance created by
[https://github.com/django/django/blob/master/django/db/models/query.py#L1608-L1615
calling the all() method on the related manager] (e.g.
`parent.child_set.all()`).
If we were to fix this we should add a branch that reuses the queryset
provided to the `Prefetch` object and `filter()` it by the related manager
lookups (e.g. `qs.filter(parent=parent)`).
Retrieving these related manager lookups is a problem in itself as the
forward many to one and reverse many to many managers don't expose a
common method to ''bind'' and existing queryset to a model instance. This
would require factoring out the logic of these managers `get_queryset()`
methods into a new method that accepts an existing queryset the
`prefetch_one_level` function could hook into.
An other issue is the fact the `prefetch_one_level` function doesn't seem
to have access to the queryset specified by to the `Prefetch` object. This
would need to be passed along somehow.
The last remaining point is performance. This change will require the
creation of multiple querysets (which is pretty slow due to `.query`
cloning).
e.g.
{{{#!python
parents = Parent.objects.prefetch_related(
Prefetch(
'children',
Child.objects.prefetch_related(
Prefetch(
'friends',
Friend.objects.order_by('saved_dt')
)
).order_by('saved_dt')
)
)
}}}
Would require the creation of `len(parents) + sum(len(parent.children) for
parent in parents))` extra querysets. It's hard to figure out the order of
the slowdown without benchmark but it's something we should keep in mind
as prefetching is used as a performance enhancement technique.
--
Ticket URL: <https://code.djangoproject.com/ticket/26226#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/067.f9af26d98b9d1ef8e004a4898c2cc91d%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.