#27554: Queryset evaluation fails with mix of nested and flattened prefetches
(AttributeError on RelatedManager)
-------------------------------------+-------------------------------------
               Reporter:  Anthony    |          Owner:  nobody
  Leontiev                           |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  1.10
  layer (models, ORM)                |       Keywords:  prefetch
               Severity:  Normal     |  AttributeError prefetch_related
           Triage Stage:             |  nested RelatedManager
  Unreviewed                         |      Has patch:  0
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 Under certain circumstances, querysets with nested prefetches fail to
 evaluate in Django 1.10.

 With these models (populated with data):

 {{{
 #  A <-> B <-- C --> D
 #        \__________/


 class A(models.Model):
     pass


 class B(models.Model):
     a = models.OneToOneField('A', null=True, related_name='b')
     d = models.ManyToManyField('D', through='C', related_name='b')


 class C(models.Model):
     b = models.ForeignKey('B', related_name='c')
     d = models.ForeignKey('D', related_name='c')


 class D(models.Model):
     pass
 }}}

 ... and this query/evaluation:

 {{{
     queryset = A.objects.all().prefetch_related(
         Prefetch(
             'b',
             queryset=B.objects.all().prefetch_related(
                 Prefetch('c__d')
             )
         )
     )
     content = queryset[0].b.c.all()[0].d.pk
 }}}

 Django throws this exception:

 {{{
   File "/Users/ant/code/django-bugs/prefetchbug/.venv/lib/python2.7/site-
 packages/django/db/models/query.py", line 256, in __iter__
     self._fetch_all()
   File "/Users/ant/code/django-bugs/prefetchbug/.venv/lib/python2.7/site-
 packages/django/db/models/query.py", line 1087, in _fetch_all
     self._prefetch_related_objects()
   File "/Users/ant/code/django-bugs/prefetchbug/.venv/lib/python2.7/site-
 packages/django/db/models/query.py", line 663, in
 _prefetch_related_objects
     prefetch_related_objects(self._result_cache,
 *self._prefetch_related_lookups)
   File "/Users/ant/code/django-bugs/prefetchbug/.venv/lib/python2.7/site-
 packages/django/db/models/query.py", line 1460, in
 prefetch_related_objects
     (through_attr, first_obj.__class__.__name__, lookup.prefetch_through))
 AttributeError: Cannot find 'd' on RelatedManager object, 'b__c__d' is an
 invalid parameter to prefetch_related()
 }}}

 Interestingly enough, this practically identical variant of the above
 query with a fully "nested" prefetch structure succeeds:

 {{{
     queryset = A.objects.all().prefetch_related(
         Prefetch(
             'b',
             queryset=B.objects.all().prefetch_related(
                 Prefetch(
                     'c',
                     queryset=C.objects.all().prefetch_related(
                         'd'
                     )
                 )
             )
         )
     )
     content = queryset[0].b.c.all()[0].d.pk
 }}}


 To reproduce, download the attachment and run:

 {{{
 pip install -r requirements.txt
 python manage.py migrate
 python manage.py runserver
 }}}

 ... and navigate to {localhost:8000/flat} and {localhost:8000/nested}.

 This only seems to impact Django 1.10; the bug does not reproduce if the
 Django version in the {requirements.txt} file is changed to 1.9 or 1.8.

 Discovered in https://github.com/AltSchool/dynamic-rest/pull/147
 Similar to https://code.djangoproject.com/ticket/26801

--
Ticket URL: <https://code.djangoproject.com/ticket/27554>
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/052.bf8ec19593cd94e61162767dd14fa0ca%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to