Django 中的 JSONP 装饰器
JSONP decorator in Django
JSONP 装饰器允许将标准 application/json
响应 return 编辑为 callback
参数中定义的 Javascript 函数。
在这种情况下,我使用 JsonResponse(HttpResponse 的子类)并且 if
条件导致函数 return 原始响应而不是 JSONP 格式化响应。我会说这是因为 simplejson
解析器与 HttpResponse
对象不兼容。
问题是如何让它兼容JsonResponse
?
JSON 响应 https://www.domain.com/data.json
:
{"doc": "546546545", "order": "98745", "nothing": "0.0"}
JSONP 回复 https://www.domain.com/data.json?callback=jQuery111305146260466426611_1448872734459
:
jQuery111305146260466426611_1448872734459({"doc": "546546545", "order": "98745", "nothing": "0.0"});
views.py:
from django.http import JsonResponse
from collections import OrderedDict
from polls.jsonp_decorator import json_response
@json_response
def sampledata(request):
data = OrderedDict([('doc', '546546545'), ('order', '98745'), ('nothing', '0.0')])
return JsonResponse(data)
jsonp_decorator.py:
from django.http import HttpResponse
import simplejson
def json_response(func):
def decorator(request, *args, **kwargs):
objects = func(request, *args, **kwargs)
if isinstance(objects, HttpResponse): #here it returns objects
return objects
try:
data = simplejson.dumps(objects)
if 'callback' in request.REQUEST:
# A jsonp response!
data = '%s(%s);' % (request.REQUEST['callback'], data)
return HttpResponse(data, 'text/javascript; charset=utf-8')
except:
data = simplejson.dumps(str(objects))
return HttpResponse(data, 'application/json; charset=utf-8')
return decorator
这里有一些问题。
首先,isinstance
return对于子类是正确的;所以如果 objects
是 JsonResponse,则 isinstance(objects, HttpResponse)
为真。
其次,JsonResponse 已经序列化为JSON;调用 simplejson.dumps()
是没有意义的。如果你想使用这个装饰器,你应该 return 来自视图函数的普通字典。
第三,你必须永远不会只抓住一个例外。任何事情都可能出错,而你永远不会知道 - 因此你不确定这段代码中的问题出在哪里。只捕获你期望的异常;在这种情况下,如果某些内容不可序列化,则会引发 TypeError,因此您应该抓住它。
JSONP 装饰器允许将标准 application/json
响应 return 编辑为 callback
参数中定义的 Javascript 函数。
在这种情况下,我使用 JsonResponse(HttpResponse 的子类)并且 if
条件导致函数 return 原始响应而不是 JSONP 格式化响应。我会说这是因为 simplejson
解析器与 HttpResponse
对象不兼容。
问题是如何让它兼容JsonResponse
?
JSON 响应 https://www.domain.com/data.json
:
{"doc": "546546545", "order": "98745", "nothing": "0.0"}
JSONP 回复 https://www.domain.com/data.json?callback=jQuery111305146260466426611_1448872734459
:
jQuery111305146260466426611_1448872734459({"doc": "546546545", "order": "98745", "nothing": "0.0"});
views.py:
from django.http import JsonResponse
from collections import OrderedDict
from polls.jsonp_decorator import json_response
@json_response
def sampledata(request):
data = OrderedDict([('doc', '546546545'), ('order', '98745'), ('nothing', '0.0')])
return JsonResponse(data)
jsonp_decorator.py:
from django.http import HttpResponse
import simplejson
def json_response(func):
def decorator(request, *args, **kwargs):
objects = func(request, *args, **kwargs)
if isinstance(objects, HttpResponse): #here it returns objects
return objects
try:
data = simplejson.dumps(objects)
if 'callback' in request.REQUEST:
# A jsonp response!
data = '%s(%s);' % (request.REQUEST['callback'], data)
return HttpResponse(data, 'text/javascript; charset=utf-8')
except:
data = simplejson.dumps(str(objects))
return HttpResponse(data, 'application/json; charset=utf-8')
return decorator
这里有一些问题。
首先,isinstance
return对于子类是正确的;所以如果 objects
是 JsonResponse,则 isinstance(objects, HttpResponse)
为真。
其次,JsonResponse 已经序列化为JSON;调用 simplejson.dumps()
是没有意义的。如果你想使用这个装饰器,你应该 return 来自视图函数的普通字典。
第三,你必须永远不会只抓住一个例外。任何事情都可能出错,而你永远不会知道 - 因此你不确定这段代码中的问题出在哪里。只捕获你期望的异常;在这种情况下,如果某些内容不可序列化,则会引发 TypeError,因此您应该抓住它。