Hassan Baig
Hassan Baig

Reputation: 15824

Diagnosing AttributeError in Django view

In a Django project of mine, I've written simple webhook logic that pings a url for certain payload if some condition is met. Here's the code:

@csrf_exempt
def webhook_event(request,*args,**kwargs):
    if request.method == 'POST':
        data = json.loads(request.body)
        event_type = data['event']
        # use CDN URL from webhook payload
        if event_type == 'project.datafile_updated':
            url = data['data']['cdn_url']
            config_manager.set_obj(url)
            return json.dumps({'success':True}), 200, {'ContentType':'application/json'} 
        return json.dumps({'success':False}), 400, {'ContentType':'application/json'}
    else:
        return render(request,"404.html",{})

I'm using the following to test it:

import requests
import json

# Update project_id
project_id = "<some_id>"

data = {"timestamp": 1463602412, "project_id": project_id, "data": {"cdn_url": "https://cdn.example.com/json/{0}.json".format(project_id), "origin_url": "https://example.s3.amazonaws.com/json/{0}.json".format(project_id), "revision": 15}, "event": "project.datafile_updated"}

r = requests.post("http://127.0.0.1:8000/ohook/", data=json.dumps(data), headers={'Content-Type': 'application/json'})
print r

It all works perfectly, but the tuple returned by webhook_event is giving me the following error:

Internal Server Error: /ohook/
Traceback (most recent call last):
  File "/home/hassan/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in get_response
    response = middleware_method(request, response)
  File "/home/hassan/.virtualenvs/myenv/local/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/hooks/framework_django.py", line 328, in wrapper
    return wrapped(*args, **kwargs)
  File "/home/hassan/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/middleware/clickjacking.py", line 30, in process_response
    if response.get('X-Frame-Options', None) is not None:
AttributeError: 'tuple' object has no attribute 'get'

Can anyone help me diagnose this?

Upvotes: 3

Views: 33

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599620

As the error says, you're returning a tuple: the JSON, an integer (presumably the status code) and a dict (presumably the headers).

Even if you fixed this, you can't just return JSON from a view; you have to return an instance of HttpResponse or one of its subclasses.

Instead of doing return json.dumps(...) in your POST blocks, you should use JsonResponse. This accepts a Python datastructure and returns a response containing the serialized JSON; as a bonus, it also sets the content-type appropriately.

if event_type == 'project.datafile_updated':
    ...
    return JsonResponse({'success':True})
return JsonResponse({'success':False}, status=400)

(Note that render is explicitly a shortcut which renders a template and returns it as an HttpResponse; this isn't the case with json.dumps().)

Upvotes: 4

Related Questions