Opened 5 years ago

Closed 5 years ago

#30957 closed Cleanup/optimization (wontfix)

Inconsistent slice behaviour on cached vs non-cached result lists in QuerySets.

Reported by: Karolis Ryselis Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

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

Change History (1)

comment:1 by Mariusz Felisiak, 5 years ago

Component: UncategorizedDatabase layer (models, ORM)
Resolution: wontfix
Status: newclosed
Summary: Inconsistent slice behaviour on cached vs non-cached result lists in QuerySetsInconsistent slice behaviour on cached vs non-cached result lists in QuerySets.
Type: UncategorizedCleanup/optimization
Version: 2.2master

Thanks for this ticket, however this is not a bug. This documented behavior is by design.

Note: See TracTickets for help on using tickets.
Back to Top