2012年9月19日水曜日

djangoでjsonpを返す

クロスドメインでjsonデータのやり取りするアプリを開発していた時に
ブラウザからアクセスするとちゃんと返ってくるのに、
「$.getJSON」や「$.ajax」を使うとHTTPレスポンス200なのにエラーが返ってくる現象に出くわした。

しばらく悩んでたらajaxのポリシーでクロスドメインにアクセスするときはjsonpを使う必要があるようだった。

どういったものなのかというと、通常はjsonそのまま渡すのに対して、
jsonpは、queryに書かれたcallback名で囲ってapplication/javascriptで返すようになる。


jsonの場合
 http://127.0.0.1/sample/

 {data1:1, data2:"hello"}

jsonpの場合
 http://127.0.0.1/sample/?callback=jsonp_1234&_=2345

 jsonp_12345({data1:1, data2:"hello"});



実装方法は下にまとめてみた。

まずはjavascript側から


$.getJSON('http://127.0.0.1/sample/?callback=?', function(data){console.dir(data);});

$.ajax({url:'http://127.0.0.1/sample/', dataType='jsonp', success: function(data){console.dir(data);});


次にサーバ側(django)もjsonpに対応

def JSONP(f):
    """
        Usage:

        @JSONP
        def func(request):
            dic = { 'data1': 1, 'data2': 'hello'}
            return dic
    """
    def _func(*args, **kwargs):
        request = args[0]
        callback = request.GET.get('callback', None)
        dic = f(request)
        ret = json.dumps(dic)
       
        if callback is None:
            ct = 'application/json'
        else:
            ret = '%s(%s);' % (callback, ret)
            ct = 'application/javascript'

        return HttpResponse(ret, mimetype=ct)

    return _func

0 件のコメント:

Androider