0

你可以猜到我遇到了一个非常奇怪的问题。我有一个查询集,它什么都不返回(即使它应该返回)但在使用 count() 时仍然返回一个值。

以下是模型:

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

这是因 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

在设置断点后,我运行了以下几行:

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

这是 django 中的错误吗?如果不是怎么回事?

PS:我使用的是 django 1.5.1

编辑:使用管理 shell_plus 也会发生同样的情况

4

1 回答 1

0

好的,所以我弄清楚了我的问题出在哪里,它在init函数中,我摆脱了它并改用了我的经理的代码,但我仍然认为 django 方面的查询集有问题。

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()
        salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
        username = user.username
        if isinstance(username, unicode):
            username = username.encode('utf-8')
        request.token = hashlib.sha1(salt+username).hexdigest()
        request.user = user
        request.save()
        return request

编辑:

似乎发生了两件事:

1)您以与 Django 期望的不兼容的方式覆盖了模型的 init。您不能将用户 arg 添加到其中,您可以使用用户 kwarg 代替。基本上,签名必须是 *args、**kwargs,否则 Django 将无法从 DB 加载您的模型。

2) Python (IIRC) 中有一个错误导致 list(qs) 中的错误吞下错误并返回空列表。这在 1.6 中已修复。

看来这个错误在 1.6 中已修复。

https://code.djangoproject.com/ticket/20795#comment:4

于 2013-07-24T06:58:23.523 回答