[Django] #20795: Weird queryset behaviour and count() method

12 views
Skip to first unread message

Django

unread,
Jul 24, 2013, 3:07:31 AM7/24/13
to django-...@googlegroups.com
#20795: Weird queryset behaviour and count() method
----------------------------------------------+----------------------------
Reporter: maa@… | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: 1.5
Severity: Release blocker | Keywords: count queryset
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+----------------------------
I am having a really weird issue.
I have a queryset who returns nothing(even when it should) but still
returns a value of one when using count() on it.

Here are the models:

import hashlib
import random
from django.contrib.auth import get_user_model
from django.db import models


class EmailChangeLogManager(models.Manager):
def get_query_set(self):
return super(EmailChangeLogManager,
self).get_query_set().filter(state=EmailChangeLog.PENDING)

def create_new_request(self, user):
request = self.model(user=user)
request.save()
return request


class EmailChangeLog(models.Model):
"""
logs the users requests to change their email
"""
PENDING = 0
CHANGED = 1

objects = EmailChangeLogManager()

user = models.ForeignKey(get_user_model())
token = models.CharField(max_length=40, primary_key=True) #
primary key so it blows up in case of collision
state = models.SmallIntegerField()
new_email = models.CharField(max_length=30)

def __init__(self, user, * args, **kwargs):
super(EmailChangeLog, self).__init__(self, *args, **kwargs)
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
username = user.username
if isinstance(username, unicode):
username = username.encode('utf-8')
self.token = hashlib.sha1(salt+username).hexdigest()
self.user = user
self.state = EmailChangeLog.PENDING

And here is the part of the view who fails with IndexError:

if EmailChangeLog.objects.filter(user=self.request.user,
state=EmailChangeLog.PENDING).count() > 0:
context['new_email'] =
EmailChangeLog.objects.filter(user=self.request.user,
state=EmailChangeLog.PENDING)[0].new_email

I ran the following lines after after putting a break point:

>>> EmailChangeLog.objects.filter(user=self.request.user,
state=EmailChangeLog.PENDING).count()
Out[1]: 1
>>> EmailChangeLog.objects.filter(user=self.request.user,
state=EmailChangeLog.PENDING)
Out[2]: []
>>> EmailChangeLog.objects.all().count()
Out[3]: 2
>>> EmailChangeLog.objects.filter(user=self.request.user,
state=EmailChangeLog.PENDING).count()
Out[4]: 1
>>> EmailChangeLog.objects.filter(user=self.request.user,
state=EmailChangeLog.PENDING)
Out[5]: []
>>> EmailChangeLog.objects.all().count()
Out[6]: 2
>>> EmailChangeLog.objects.all()
Out[7]: []
>>> EmailChangeLog.objects.filter(user=self.request.user)
Out[8]: []
>>> EmailChangeLog.objects.filter(state=EmailChangeLog.PENDING)
Out[9]: []
>>> EmailChangeLog.objects.filter()
Out[10]: []
>>> EmailChangeLog.objects.all()
Out[11]: []
>>> EmailChangeLog.objects.all().count()
Out[1]: 2
>>> EmailChangeLog.objects.all()
Out[3]: []
>>> EmailChangeLog.objects.all()
Out[5]: []
>>> EmailChangeLog.objects.all().count()
Out[6]: 2
>>> EmailChangeLog.objects.all().count()
Out[7]: 2
>>> az = EmailChangeLog.objects.all()
>>> az
Out[9]: []
>>> az.count()
Out[10]: 2

Is this a bug in django ? If not what is going on ?
I am using django 1.5.1
The same happens using manage shell_plus

I got rid of it by using a manager's method instead of the __init__
function, if somehow this is not a bug can you please tell me what is
going on and how can an empty queryset return a value greater than zero ?

Thanks.

--
Ticket URL: <https://code.djangoproject.com/ticket/20795>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 24, 2013, 8:58:25 PM7/24/13
to django-...@googlegroups.com
#20795: Weird queryset behaviour and count() method
-------------------------------------+-------------------------------------

Reporter: maa@… | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.5
(models, ORM) | Resolution:
Severity: Release blocker | Triage Stage:
Keywords: count queryset | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by CollinAnderson):

* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


Comment:

What does your unicode method look like?
What does len(EmailChangeLog.objects.all()) return?
Do you have any other manager methods?
Could you narrow your problematic models down to the simplest form while
still being able to reproduce the problem, and then share them somewhere?

--
Ticket URL: <https://code.djangoproject.com/ticket/20795#comment:1>

Django

unread,
Jul 25, 2013, 3:11:49 AM7/25/13
to django-...@googlegroups.com
#20795: Weird queryset behaviour and count() method
-------------------------------------+-------------------------------------

Reporter: maa@… | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.5
(models, ORM) | Resolution:
Severity: Release blocker | Triage Stage:
Keywords: count queryset | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by maa@…):

I dont have a unicode method.
len(EmailChangeLog.objects.all()) fails with AttributeError: 'int' object
has no attribute 'username'
traceback :
{{{
/home/maa/.virtualenvs/django_myproject/local/lib/python2.7/site-
packages/django/db/models/query.pyc in __len__(self)
88 self._result_cache = list(self._iter)
89 else:
---> 90 self._result_cache = list(self.iterator())
91 elif self._iter:
92 self._result_cache.extend(self._iter)

/home/maa/.virtualenvs/django_myproject/local/lib/python2.7/site-
packages/django/db/models/query.pyc in iterator(self)
309 obj = model_cls(**dict(zip(init_list,
row_data)))
310 else:
--> 311 obj = model(*row_data)
312
313 # Store the source database of the object

/home/maa/PycharmProjects/django_myproject/my_home/models.pyc in
__init__(self, user, *args, **kwargs)
41 super(EmailChangeLog, self).__init__(self, *args,
**kwargs)
42 salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
---> 43 username = user.username
44 if isinstance(username, unicode):
45 username = username.encode('utf-8')

AttributeError: 'int' object has no attribute 'username'

}}}
My manager has only one method and did n"t use it.
I have only one model and I already gave my 'models.py' code here is a
pastebin : http://pastebin.com/0qSkeveT
Their is no view code involved, the same weird behaviour happens with the
'manage.py shell_plus' command.
Also I am using postgresql 8.4.17 on ubuntu 12.04 LTS, thanks for your
support.

--
Ticket URL: <https://code.djangoproject.com/ticket/20795#comment:2>

Django

unread,
Jul 25, 2013, 4:12:23 AM7/25/13
to django-...@googlegroups.com
#20795: Weird queryset behaviour and count() method
-------------------------------------+-------------------------------------
Reporter: maa@… | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.5
(models, ORM) | Resolution: invalid

Severity: Release blocker | Triage Stage:
Keywords: count queryset | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by akaariai):

* status: new => closed
* resolution: => invalid


Comment:

There seems to be two things going on:
1) You have overriden the model's init in a way that is incompatible to
what Django expects. You can't add user arg to it, you might be able to
use user kwarg instead. Basically, the signature must be `*args,
**kwargs`, or Django will not be able to load your models back from DB.
2) There is a bug in Python (IIRC) that causes errors inside list(qs) to
swallow the error and return empty list. This is fixed in 1.6.

So, marking this as invalid.

--
Ticket URL: <https://code.djangoproject.com/ticket/20795#comment:3>

Django

unread,
Jul 26, 2013, 3:18:16 AM7/26/13
to django-...@googlegroups.com
#20795: Weird queryset behaviour and count() method
-------------------------------------+-------------------------------------
Reporter: maa@… | Owner: nobody

Type: Bug | Status: closed
Component: Database layer | Version: 1.5
(models, ORM) | Resolution: invalid
Severity: Release blocker | Triage Stage:
Keywords: count queryset | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by anonymous):

thanks for the update.

--
Ticket URL: <https://code.djangoproject.com/ticket/20795#comment:4>

Reply all
Reply to author
Forward
0 new messages