1

I have a number of views in a Django app that all return something like this:

return HttpResponse(jsonpickle.encode(data, unpicklable=False), 'application/json')

This works well, but I'd like to create an abstraction over the JSON encoding and creating the response object, so that I can do something like

return JsonResponse(data)

and the class JsonResponse does all the heavy lifting for me.

I tried something like this:

class JsonResponse(HttpResponse):
    def __init__(self, obj):
        super(HttpResponse, self).__init__(jsonpickle.encode(obj, unpicklable=False), 'application/json')

but when I have that, I get the standard A server error occurred. Please contact the administrator. when I view the web page. I've also tried with self as the first argument to the inner call to __init__ as well as with the arguments named (content and content_type respectively) and with and without a named status=200. Neither of these changes seem to change anything.

The terminal output from the dev server is a little more descriptive, but not by much:

Traceback (most recent call last):
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run
    self.result = application(self.environ, self.start_response)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.5.1-py2.7.egg/django/core/handlers/wsgi.py", line 267, in __call__
    start_response(force_str(status), response_headers)
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 175, in start_response
    assert int(status[:3]),"Status message must begin w/3-digit code"
ValueError: invalid literal for int() with base 10: 'app'
[02/Jun/2013 00:51:06] "GET / HTTP/1.1" 500 59

I know I could just create a method that returns the HttpResponse instead, like so:

def json(obj):
    return HttpResponse(...)

but I'd like to learn a way to do this the way I originally imagined it if it's possible - if nothing else then for my learning (and it also seems to align with the design of Django, which I like).

Is there a way to get a subclass like JsonResponse above to work? If so, what am I doing wrong?

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402

1 Answers1

4

You have to pass JsonResponse as the first argument of super, otherwise you are calling the constructor of HttpResponseBase:

class JsonResponse(HttpResponse):
    def __init__(self, obj):
        super(JsonResponse, self).__init__(jsonpickle.encode(obj, unpicklable=False), 'application/json')
A. Rodas
  • 20,171
  • 8
  • 62
  • 72
  • The problem wasn't related to Django at all, then, but to my incorrect understanding of what `super` does =) Thanks! – Tomas Aschan Jun 01 '13 at 23:17