Django WSGI如何正确封装纯JSON/JSONP内容构造响应返回
问题根因
Django 要求所有视图函数必须返回继承自 HttpResponse 的标准响应对象,直接返回普通字符串、字典等原生Python对象时,后续执行的响应中间件(报错栈里是点击劫持防护中间件)会尝试访问响应对象的headers属性添加安全头,原生对象没有这个属性就会抛出500错误。
修复方案
你的场景里planetor.generate()已经返回了拼接好callback的完整JSONP文本,不需要额外做序列化,直接用HttpResponse封装即可,注意要指定正确的MIME类型:
- 先调整导入,引入基础响应类
from django.http import HttpResponse - 修改视图函数的返回逻辑
def generate_planet(request): res = planetor.generate(request.content_params, "/app/planetor/", "FRAMES=1") # JSONP本质是可执行JavaScript,指定对应Content-Type确保浏览器正常解析 return HttpResponse(res, content_type="application/javascript")
注意事项
- 不要用
JsonResponse处理JSONP响应:JsonResponse会自动把传入内容序列化为标准JSON格式,且默认把Content-Type设为application/json,浏览器拿到后不会作为脚本执行,会导致JSONP逻辑失效。 - 不需要手动构造底层WSGI响应对象:Django提供的
HttpResponse已经完成了WSGI层的标准封装,直接使用即可满足框架要求,构造时常用参数包括:- 第一个位置参数:响应体的字符串内容
content_type:指定响应的MIME类型status:指定HTTP响应状态码,默认200
- 如果后续调整逻辑,需要自己拼接JSONP,可以参考如下写法(对应
planetor.generate()返回Python字典的场景):import json from django.http import HttpResponse def generate_planet(request): data = planetor.generate(request.content_params, "/app/planetor/", "FRAMES=1") # 从请求参数取前端传的回调函数名 callback_name = request.GET.get("callback", "callback") json_content = json.dumps(data) jsonp_content = f"{callback_name}({json_content})" return HttpResponse(jsonp_content, content_type="application/javascript") - 纯JSON接口场景直接使用
JsonResponse即可,它是HttpResponse的子类,会自动完成JSON序列化和MIME类型设置,不需要额外封装。
内容的提问来源于stack exchange,提问作者Walt Howard
相关产品推荐
相关产品推荐

