Opened 9 years ago
Closed 9 years ago
#25894 closed Bug (fixed)
Evaluation of zero-length slices of queryset.values() fails
Reported by: | Marc DEBUREAUX | Owned by: | Sergey Fedoseev |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.9 |
Severity: | Release blocker | Keywords: | |
Cc: | marc@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When using a QuerySet returning no values without a whole model behind, the Paginator fails to display data from page.
Example OK:
queryset = Model.objects.filter(my_filter_return_nothing=value) paginator = Paginator(queryset, 10) list(paginator.page(1)) >>> []
Example KO:
queryset = Model.objects.values('whatever_field').filter(my_filter_return_nothing=value) paginator = Paginator(queryset, 10) list(paginator.page(1)) >>> --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-38-56e5635092e7> in <module>() ----> 1 list(paginator.page(1)) \lib\site-packages\django\core\paginator.py in __len__(self) 115 116 def __len__(self): --> 117 return len(self.object_list) 118 119 def __getitem__(self, index): \lib\site-packages\django\db\models\query.py in __len__(self) 238 239 def __len__(self): --> 240 self._fetch_all() 241 return len(self._result_cache) 242 \lib\site-packages\django\db\models\query.py in _fetch_all(self) 1072 def _fetch_all(self): 1073 if self._result_cache is None: -> 1074 self._result_cache = list(self.iterator()) 1075 if self._prefetch_related_lookups and not self._prefetch_done: 1076 self._prefetch_related_objects() \lib\site-packages\django\db\models\query.py in __iter__(self) 110 names = extra_names + field_names + annotation_names 111 --> 112 for row in compiler.results_iter(): 113 yield dict(zip(names, row)) 114 \lib\site-packages\django\db\models\sql\compiler.py in results_iter(self, results) 805 if results is None: 806 results = self.execute_sql(MULTI) --> 807 fields = [s[0] for s in self.select[0:self.col_count]] 808 converters = self.get_converters(fields) 809 for rows in results: AttributeError: 'SQLCompiler' object has no attribute 'col_count'
Thanks.
Change History (20)
comment:1 by , 9 years ago
Cc: | added |
---|---|
Severity: | Normal → Release blocker |
comment:2 by , 9 years ago
comment:4 by , 9 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:5 by , 9 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:6 by , 9 years ago
Bisected to afe0bb7b13bb8dc4370f32225238012c873b0ee3.
Minimal example to reproduce:
from django.contrib.contenttypes.models import ContentType list(ContentType.objects.values('model')[0:0])
comment:7 by , 9 years ago
Quick and dirty monkey patch.
# django monkey patch # https://code.djangoproject.com/ticket/25894 try: from django.db.models.sql.compiler import SQLCompiler def _results_iter(self, results=None): if not hasattr(self, 'col_count'): self.col_count = 0 if not self.select: self.select = [] return self._results_iter(results) SQLCompiler._results_iter = SQLCompiler.results_iter SQLCompiler.results_iter = _results_iter except: pass
May not work with everything.
comment:9 by , 9 years ago
Component: | Core (Other) → Database layer (models, ORM) |
---|---|
Summary: | Paginator fails with QuerySet returning no values → Evaluation of zero-length slices of queryset.values() fails |
comment:10 by , 9 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:13 by , 9 years ago
Has patch: | unset |
---|---|
Resolution: | fixed |
Status: | closed → new |
Triage Stage: | Ready for checkin → Accepted |
The new test doesn't pass on Oracle.
====================================================================== ERROR: test_zero_length_values_slicing (queries.tests.WeirdQuerysetSlicingTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/tim/code/django/tests/queries/tests.py", line 2435, in test_zero_length_values_slicing self.assertQuerysetEqual(Article.objects.values()[n:n], []) File "/home/tim/code/django/django/test/testcases.py", line 933, in assertQuerysetEqual items = six.moves.map(transform, qs) File "/home/tim/code/django/django/db/models/query.py", line 258, in __iter__ self._fetch_all() File "/home/tim/code/django/django/db/models/query.py", line 1072, in _fetch_all self._result_cache = list(self.iterator()) File "/home/tim/code/django/django/db/models/query.py", line 112, in __iter__ for row in compiler.results_iter(): File "/home/tim/code/django/django/db/models/sql/compiler.py", line 792, in results_iter fields = [s[0] for s in self.select[0:self.col_count]] AttributeError: 'SQLCompiler' object has no attribute 'col_count'
comment:14 by , 9 years ago
Status: | new → assigned |
---|
comment:15 by , 9 years ago
Has patch: | set |
---|
On oracle this seems to be broken since 1.8.
PR -- https://github.com/django/django/pull/5834
comment:18 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
comment:19 by , 9 years ago
Resolution: | fixed |
---|---|
Status: | closed → new |
It doesn't work with the following case:
from django.contrib.contenttypes.models import ContentType list(ContentType.objects.values('model')[0:0])
Here the patch I use based on the last commit. Does I miss something else?
try: def _set_limits(self, low=None, high=None): self._set_limits(low, high) if self.low_mark == self.high_mark: self.set_empty() from django.db.models.sql.query import Query Query._set_limits = Query.set_limits Query.set_limits = _set_limits except: pass
comment:20 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Nevermind, I forgot to delete lines from compiler.
Is this a regression in Django 1.9? Can you provide a test for
tests/pagination/tests.py
?