﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
27554	Queryset evaluation fails with mix of nested and flattened prefetches (AttributeError on RelatedManager)	Anthony Leontiev	François Freitag	"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"	Bug	closed	Database layer (models, ORM)	1.10	Release blocker	fixed	prefetch AttributeError prefetch_related nested RelatedManager	mail@…	Ready for checkin	1	0	0	0	0	0
