1

Django 会在 process_response 之后展平响应吗?

我有这个模型(简化版):

class Ticket(models.Model):
    uuid = UUIDField(primary_key = True)
    is_active = models.BooleanField(default = False)
    remains = models.IntegerField(default = 2)

    def __unicode__(self):
        return '%s' % (self.is_active)

和中间件(简化):

class TicketMiddleware(object):
    def process_request(self, request):
        # ...
        try:
            request.ticket = Ticket.objects.get(uuid_exact=request.GET['ticket'], is_active=True)
            print '%s %d' % (request.ticket.is_active, request.ticket.remains)
            # first case:
            return HttpResponse(request.ticket)
            # second case:
            #return HttpResponse(request.ticket.is_active)
        except Ticket.DoesNotExists:
            return HttpResponseForbidden()

    def process_response(self, request, response):
        if request.ticket is not None and request.ticket.remains > 0:
            request.ticket.remains -= 1
            if request.ticket.remains == 0:
                request.ticket.is_active = False
            request.ticket.save()
        return response

在第一种情况下,我在第四次请求时获得了禁止页面:

   RESPONSE     PRINT
1: True         True 2
2: False        True 1
3: False        True 1
4: Forbidden

在第二种情况下,我在第三次请求时获得了禁止页面:

   RESPONSE     PRINT
1: True         True 2
2: True         True 1
3: Forbidden

这第二种情况是我想要的方式。为什么我必须首先对模型进行字符串化才能正常流动?我误解了什么?

django.VERSION = (1, 2, 3, 'final', 0)

编辑

我发现了问题。在实际代码中,我为 django.contrib.auth.models.User 使用外键,并使用关联用户的用户名对我的 Ticket 模型进行 unicoding:

class Ticket(models.Model):
    # ...
    user = models.ForeignKey(User)

    def __unicode__(self):
        # this works as expected
        return u'%s' % (self.is_active)
        # with this I have unexpected third step in first case
        # but I dont understand why
        #return u'%s %s' % (self.user.username, self.is_active)
4

1 回答 1

3

我真的怀疑第一个案例显示两次False。我用你的代码做了一个简单的测试,它显示第一种情况:

1: True
2: False
3: Forbidden

这是预期的行为。只要process_response修改is_active数据并在第二次调用时保存票证,我看不出第三次调用如何返回 False ......除非票证.remains 以某种方式被修改。使用此处显示的代码,我看不出如何process_response使用 保存票证is_active=False,并且在随后的请求process_request中不重定向到Forbidden...您使用哪个 Django 版本?也打印ticket.remains__unicode__()里面看看它是如何变化的......

False您在第一种情况下进行第二次调用的原因是您传递了一个模型实例

return HttpResponse(request.ticket)

ticket.__unicode__()被调用之后process_response,在最终HttpResponse()向客户端写入内容的过程中,被调用。并且由于在第一个场景ticket.is_active中被修改process_response,当 ticket.__unicode__()最终被调用时,它会得到修改后的ticket.is_activeFalse

在第二种情况下,__unicode__在 process_request 中显式调用并评估为“True”。

于 2012-07-31T11:31:43.320 回答