Opened 13 years ago

Closed 11 years ago

#15959 closed Bug (fixed)

.values()/.values_list() fails on EmptyQuerySet

Reported by: Davide Rizzo <mail@…> Owned by: nobody
Component: Database layer (models, ORM) Version: 1.2
Severity: Normal Keywords: dceu2011
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

Calling .values() or .values_list() on an EmptyQuerySet raises an exception.

>>> EmptyQuerySet().values('id')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 515, in values
    return self._clone(klass=ValuesQuerySet, setup=True, _fields=fields)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1049, in _clone
    c = super(EmptyQuerySet, self)._clone(klass, setup=setup, **kwargs)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 772, in _clone
    c._setup_query()
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 895, in _setup_query
    self.query.add_fields(self.field_names, False)
  File "C:\Python27\lib\site-packages\django\db\models\sql\query.py", line 1549, in add_fields
    alias = self.get_initial_alias()
  File "C:\Python27\lib\site-packages\django\db\models\sql\query.py", line 798, in get_initial_alias
    alias = self.join((None, self.model._meta.db_table, None, None))
AttributeError: 'NoneType' object has no attribute '_meta'
>>> EmptyQuerySet().values_list('id')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 525, in values_list
    _fields=fields)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1049, in _clone
    c = super(EmptyQuerySet, self)._clone(klass, setup=setup, **kwargs)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 772, in _clone
    c._setup_query()
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 895, in _setup_query
    self.query.add_fields(self.field_names, False)
  File "C:\Python27\lib\site-packages\django\db\models\sql\query.py", line 1549, in add_fields
    alias = self.get_initial_alias()
  File "C:\Python27\lib\site-packages\django\db\models\sql\query.py", line 798, in get_initial_alias
    alias = self.join((None, self.model._meta.db_table, None, None))
AttributeError: 'NoneType' object has no attribute '_meta'

This seems related to #7235. I can reproduce the bug on 1.2.4 and 1.2.5 but not on 1.2.3.

### Django 1.2.3
>>> q = EmptyQuerySet()
>>> q.values_list('id')
[]

Attachments (1)

15959-r16345.diff (1.4 KB ) - added by Victor van den Elzen <victor.van.den.elzen@…> 13 years ago.

Download all attachments as: .zip

Change History (7)

comment:1 by Aymeric Augustin, 13 years ago

Triage Stage: UnreviewedAccepted

comment:2 by Victor van den Elzen <victor.van.den.elzen@…>, 13 years ago

Has patch: set
UI/UX: unset

Like #7235, on the one hand, you shouldn't really use EmptyQuerySet without an associated model.

TestModel.objects.none().values('id')

works fine.

On the other hand we could just fix it. Patch attached.

by Victor van den Elzen <victor.van.den.elzen@…>, 13 years ago

Attachment: 15959-r16345.diff added

comment:3 by Davide Rizzo <mail@…>, 13 years ago

There is at least one real world use case that looks legit to me:

# user can be an instance of django.contrib.auth.AnonymousUser
user.groups.all().values_list('id', flat=True)

The patch works fine.

comment:4 by Victor van den Elzen <victor.van.den.elzen@…>, 13 years ago

Keywords: dceu2011 added

comment:5 by Malcolm Tredinnick, 13 years ago

Patch needs improvement: set

I'm not happy with this patch: it's returning the wrong type. The values() and values_list() calls return particular types that, when converted to a list, for example, are lists of dictionaries or lists of tuples. The EmptyQuerySet interface doesn't meet that.

Duck typing implies that if it looks like the result of a values() call, it should behave like one in all pertinent respects.

comment:6 by Anssi Kääriäinen <akaariai@…>, 11 years ago

Resolution: fixed
Status: newclosed

In 69a46c5ca7d4e6819096af88cd8d51174efd46df:

Tests for various emptyqs tickets

The tickets are either about different signature between qs.none() and
qs or problems with subclass types (either EmptyQS overrided the custom
qs class, or EmptyQS was overridden by another class - values() did
this).

Fixed #15959, fixed #17271, fixed #17712, fixed #19426

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