#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.