Does Django flattening response after process_response?
I have this model (simplified version):
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)
and middleware (simplified):
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
In first case I got forbidden page on fourth request:
RESPONSE PRINT
1: True True 2
2: False True 1
3: False True 1
4: Forbidden
In second case I got forbidden page on third request:
RESPONSE PRINT
1: True True 2
2: True True 1
3: Forbidden
And this second case is the way I want. Why I must stringify my model first for properly flow? What I misunderstood?
django.VERSION = (1, 2, 3, 'final', 0)
EDIT
I found the problem. In real code I use foreign key for django.contrib.auth.models.User and unicoding my Ticket model with username of associated User:
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)
I really doubt that the first case displays two times
False. I’ve made a simple test with your code, and it displays for the first case:which is the expected behavior. As long as the
process_responsemodifies theis_activedata and saves the ticket on the second call, I don’t see how a third call can return False… Unless the ticket.remains is modified somehow. With the code shown here, I can’t see how it is possible thatprocess_responseto save the ticket withis_active=False, and on subsequent requestprocess_requestnot to redirect toForbidden… Which Django version do you use? Print alsoticket.remainsin the__unicode__()to see how it changes …The reason that you get
Falsein the second call with 1st case is that you pass a model instanceThe
ticket.__unicode__()is being called after theprocess_responseis being called, during the final writing of the contents ofHttpResponse()to the client. And since in the first scenarioticket.is_activeis being modified inprocess_response, whenticket.__unicode__()is finally called, it gets the modified value ofticket.is_activewhich isFalse.In the second scenario the
__unicode__is called explicitly in process_request and evaluated to ‘True’.