Django Json Woes
Recently I have been working on a new web project, written in Python using the Django web framework. I have been using Django off and on over the last year, traditionally I really never used much of a framework. A great deal of my time prior to Python/Django work was spent on applications development for server side processes written in C#.
I have a strange love/hate relationship with python, I love some of its capabilities, ease of use, and its concise nature. On the other hand I hate that there seems to be some things that I would love to see that just isn’t there. While writing a simple view in which I planned on returning a JSON string back to the user, I found there was no “response” or internal method that I could find to return it simply. In the process of going through the documentation I found some information relating to the HttpResponse that gets returned at the end of each View. I figured that would be a great place to start.
from django.http import HttpResponse
from cjson import encode
class JsonResponse(HttpResponse):
def __init__(self, data, status = 200):
HttpResponse.__init__(self, content = encode(data), mimetype = 'application/json', status = status)
First revision looked something like this. At first it worked out doing what I had wanted, one problem I had was while using a mime type of ‘application/json’ was more secure it made debugging a little more difficult when hitting the view directly in the browser. So I figured if I was running in debug why not use a mime type of ‘text/html’, its less secure but debug should never run on production.
from django.http import HttpResponse
from django.conf import settings
from cjson import encode
class JsonResponse(HttpResponse):
def __init__(self, data, status = 200):
mimetype = 'application/json'
if(settings.DEBUG):
mimetype = 'text/html'
HttpResponse.__init__(self, content = encode(data), mimetype = mimetype, status = status)
This revision looked much more what I needed. The only problem I had was when hitting this view from Javascript on the client side, some browsers would cache the return value and an additional hit to the view wouldn’t occur. I could have solved this on the client side by adding some sort of random seed to the end of the URL. However I would much prefer my view decide when something needs to be cached rather than the JavaScript code so I made a few modifications.
from django.http import HttpResponse
from django.conf import settings
from cjson import encode
class JsonResponse(HttpResponse):
def __init__(self, data, status = 200, cache = False):
mimetype = 'application/json'
if(settings.DEBUG):
mimetype = 'text/html'
HttpResponse.__init__(self, content = encode(data), mimetype = mimetype, status = status)
if(cache == False):
self['Last-Modified'] = 'Mon, 01 Jan 1970 05:00:00 GMT'
self['Cache-Control'] = 'no-store, no-cache, must-revalidate'
self['Pragma'] = 'no-cache'
Making this change allowed me to have the flexibility of deciding if I wanted something cached, which in most instances I don’t since the data for these returns are normally always changing. With this new object I was able to perform a “standard” JSON return in a view as well as maintain a single place I can make modifications to all requests at once.
from responses import JsonResponse
def json_view(request):
x = { 'status': True, 'message': 'Success' }
return JsonResponse(x)
-
Norman Hooper
