Django 4.2 返回 JSON 的三种正确方式
Django 4.2 里正确返回 JSON 的三种方式
写 Django 接口时,返回 JSON 是最频繁的操作。但不少新手习惯用 HttpResponse 手搓 json.dumps,既容易踩字符编码的坑,又丢掉了 content-type 和状态码的语义。下面按「症状 → 根因 → 结论」梳理三种正确姿势。
症状
前端调用接口后解析失败,拿到的不是合法 JSON;或者状态码永远停在 200,错误情况也返回成功。
根因
直接用 HttpResponse(json.dumps(data)) 时,响应头 Content-Type 默认是 text/html,而且不会自动处理 ensure_ascii、日期时间等非 JSON 原生类型,前端 JSON.parse 自然报错。
结论
优先用框架自带工具:函数视图用 JsonResponse,DRF 视图用 Response 或 @api_view。下面三种场景对应三种写法。
1. 函数视图:JsonResponse
| 写法 | Content-Type | 中文处理 |
|---|---|---|
| HttpResponse + json.dumps | text/html | 需手动 ensure_ascii=False |
| JsonResponse | application/json | 默认转义为 \uXXXX |
from django.http import JsonResponse
def ping(request):
return JsonResponse({"status": "ok", "code": 0})
需要返回列表等非字典结构时,加 safe=False:
return JsonResponse([1, 2, 3], safe=False)
2. 类视图:DRF 的 APIView
from rest_framework.views import APIView
from rest_framework.response import Response
class PingView(APIView):
def get(self, request):
return Response({"status": "ok"})
Response 会自动协商内容类型(JSON 与浏览器可调试页面),并正确处理序列化。
3. 函数式 API:@api_view 装饰器
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(["GET"])
def ping(request):
return Response({"status": "ok"})
小结
- 纯 Django 函数视图:用
JsonResponse,返回列表记得safe=False - DRF 项目:用
APIView或@api_view+Response - 不要再手搓
HttpResponse(json.dumps(...)),既丢语义又易出编码 bug
照这样写的接口,前端 fetch 之后 await res.json() 才能稳定解析。
广告位占位 · post-inline