中间件:在process_request中使用模型并在process_response中修改它

时间:2012-07-31 09:46:33

标签: django django-models python-2.6 django-middleware

在process_response之后,Django是否会平缓响应?

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

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模型解锁:

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)

1 个答案:

答案 0 :(得分:3)

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

1: True
2: False
3: Forbidden

这是预期的行为。只要process_response修改is_active数据并在第二次调用时保存票证,我就看不到第三次调用如何返回False ...除非以某种方式修改ticket.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_active的修改值False

在第二个场景中,__unicode__在process_request中被显式调用,并被评估为'True'。