Code

Opened 3 years ago

Closed 18 months 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@…> 3 years ago.

Download all attachments as: .zip

Change History (7)

comment:1 Changed 3 years ago by aaugustin

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

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

  • 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.

Changed 3 years ago by Victor van den Elzen <victor.van.den.elzen@…>

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

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 Changed 3 years ago by Victor van den Elzen <victor.van.den.elzen@…>

  • Keywords dceu2011 added

comment:5 Changed 3 years ago by mtredinnick

  • 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 Changed 18 months ago by Anssi Kääriäinen <akaariai@…>

  • Resolution set to fixed
  • Status changed from new to closed

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

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.