#35677: Unexpected behaviour of Prefetch with queryset filtering on a through 
model
-------------------------------------+-------------------------------------
     Reporter:  David Glenck         |                    Owner:  (none)
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  5.1
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:  Prefetch,            |             Triage Stage:  Accepted
  prefetch_related, many-to-many     |
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Comment (by David Glenck):

 Hello Simon

 thank you for the proposed bugfix. I prepared a test and applied your
 patch and it passes with your fix.
 However, if I do an annotation after the filter (which I do in my real
 world use case). The same happens, when I add another prefetch_related
 after the filter.

 {{{#!python
 prefetched =
 Subscriber.objects.filter(pk__in=subscribers).prefetch_related(
     Prefetch(
         'subscriptions',
 
queryset=Subscription.objects.filter(status__is_active=True).annotate(active=F('status__is_active')),
         to_attr='active_subscriptions'
     )
 )
 }}}

 This makes sense, because the last filter/annotation etc. is made sticky,
 not the first, like in the case of the many-to-many manager.
 Knowing this, for some cases this can be fixed, by moving the additional
 annotation before the filter.

 But if I do an annotation like this, is seems to fail regardless:

 {{{#!python
 prefetched =
 Subscriber.objects.filter(pk__in=subscribers).prefetch_related(
     Prefetch(
         'subscriptions',
 
queryset=Subscription.objects.annotate(active=F('status__is_active')).filter(active=True),
         to_attr='active_subscriptions'
     )
 )
 }}}

 The many-to-many manager seems to handle this case correctly.
 {{{#!python
 
subscriber1.subscriptions.annotate(active=F('status__is_active')).filter(active=True)
 }}}

 I have started a branch with the tests here:
 https://github.com/django/django/compare/main...pascalfree:django:35677
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35677#comment:8>
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701916155c3de-141c62ca-98ee-4f22-8578-690adf327d45-000000%40eu-central-1.amazonses.com.

Reply via email to