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.
* 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>
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>
* 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>
Comment (by anonymous):
thanks for the update.
--
Ticket URL: <https://code.djangoproject.com/ticket/20795#comment:4>