﻿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
30957	Inconsistent slice behaviour on cached vs non-cached result lists in QuerySets.	Karolis Ryselis	nobody	"consider a model

{{{
class Good(models.Model):
    title = models.CharField(max_length=16)
}}}

Suppose we have created some objects of this model in database.

Getting a slice of existing queryset returns a new queryset:
{{{
g = Good.objects.all()
print(type(g[0:1]))
}}}

outputs
{{{
<class 'django.db.models.query.QuerySet'>
}}}

however, getting a slice on an evaluated queryset returns a list, not queryset:
{{{
g = Good.objects.all()
list(g)  # force evaluation
print(type(g[0:1]))
}}}

outputs
{{{
<class 'list'>
}}}

This happens because {{{__getitem__}}} in {{{QuerySet}}} uses result cache if it's available, and result cache is always saved as list. Excerpt from {{{QuerySet,__getitem__}}}:
{{{
        if self._result_cache is not None:
            return self._result_cache[k]
}}}

Excerpt from {{{QuerySet._fetch_all}}}:
{{{
        if self._result_cache is None:
            self._result_cache = list(self._iterable_class(self))
}}}

If {{{_result_cache}}} is {{{None}}}, then {{{__getitem__}}} makes a query and returns a proper QuerySet. This produces extremely hard-to-catch bugs, because the return type depends on QuerySet evaluation state.

The error was reproduced in version 2.2.6"	Cleanup/optimization	closed	Database layer (models, ORM)	dev	Normal	wontfix			Unreviewed	0	0	0	0	0	0
