W weiserv
← 返回博客

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