#17001: Allow usage of custom querysets in prefetch_related
-------------------------------------+-------------------------------------
     Reporter:  akaariai             |                    Owner:  loic84
         Type:  New feature          |                   Status:  assigned
    Component:  Database layer       |                  Version:  master
  (models, ORM)                      |               Resolution:
     Severity:  Normal               |             Triage Stage:  Accepted
     Keywords:  prefetch_related     |      Needs documentation:  1
    Has patch:  1                    |  Patch needs improvement:  1
  Needs tests:  1                    |                    UI/UX:  0
Easy pickings:  0                    |
-------------------------------------+-------------------------------------

Comment (by loic84):

 WIP: https://github.com/loic/django/compare/prefetch_related.

 It's rather experimental and still needs tons of work with tests and docs,
 but if anyone want to give it a try, that would help.

 `Prefetch` takes two parameters: `lookup` and an optional `queryset`.

 1. `Manager` backed lookups with `*args`:

 {{{#!python
     # Traditional string lookup:
     Restaurant.objects.prefetch_related('pizzas__toppings')

     # Equivalent with Prefetch:
     Restaurant.objects.prefetch_related(Prefetch('pizzas__toppings'))

     # Lookup with custom queryset:
     Restaurant.objects.prefetch_related(
         Prefetch('pizzas__toppings',
 queryset=Toppings.object.filter(veggie=True)))
 }}}

 2. `list` backed lookups with `**kwargs`:

 {{{#!python
     # Traditional lookup stored in a list (significantly faster, see
 #20577 and link below)
     Restaurant.objects.prefetch_related(pizza_list=Prefetch('pizzas'))

     # With custom QuerySet.
     Pizza.objects.prefetch_related(
         toppings_list=Prefetch('toppings',
 queryset=Toppings.object.filter(veggie=True))

     # Multiple level using nested prefetch_related:
     pizza_queryset = Pizza.objects.prefetch_related(
         Prefetch('toppings',
 queryset=Toppings.object.filter(veggie=True)))
     Restaurant.objects.prefetch_related(
         pizza_list=Prefetch('pizzas', queryset=pizza_queryset))

     # Alternatively, multiple level using kwarg lookups (nested
 prefetch_related actually rewrite to that):
     Restaurant.objects.prefetch_related(
         pizza_list=Prefetch('pizzas'),
         pizza_list__toppings_list=Prefetch('pizza_list__toppings',
 queryset=Toppings.object.filter(veggie=True))
 }}}

 3. Mixing both approaches:

 {{{#!python
     Restaurant.objects.prefetch_related(
         'pizza_list__toppings_list'
         'pizza_list': Prefetch('pizza'),
     )

 }}}

 4. Flattening is **not** supported, it doesn't seem trivial to implement,
 maybe for another ticket?

 {{{#!python
 Restaurant.objects.prefetch_related(
     toppings_list=Prefetch('pizzas__toppings')
 )
 }}}

 Additionally, here is a quick and dirty benchmark that compares lookups
 backed by `list` vs `Manager`:  https://gist.github.com/loic/7198193.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/17001#comment:33>
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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/066.e86a668550024af9e782d6c64ff9e87c%40djangoproject.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to