【Django】-3- 处理HTTP响应

HttpResponse 家族" 的常用操作🌟

1. 设置状态码 👋

状态码是服务器告诉客户端 "请求处理结果" 的数字暗号(比如 404 表示 "没找到页面")。Django 里有 3 种设置方式:

方式 1:直接写数字(简单粗暴)
python 复制代码
HttpResponse(html, status=404)

HttpResponse()是类的实例化,后面讲解过程中遇到诸如此类的都是实例化加上传参噢

  • 直接传 status=404,告诉客户端 "你要的页面没找到"~
方式 2:用常量(优雅不易错)
python 复制代码
from django.http import HttpResponseNotFound
# HttpResponseNotFound 的 status_code 就是 404,更语义化
HttpResponse(html, status=HttpResponseNotFound.status_code)
  • HttpResponseNotFound.status_code 本质还是 404,但用常量更易读,不容易写错数字~
方式 3:直接用响应类(最推荐!)
python 复制代码
from django.http import HttpResponseNotFound
# 直接返回 HttpResponseNotFound,自动带 404 状态码
HttpResponseNotFound(html)
  • Django 给常用状态码做了 "专属响应类"(比如 HttpResponseNotFound 对应 404HttpResponseServerError 对应 500),用这些类更简洁,还能自动设置状态码和默认响应内容~

2. 设置响应头 📄

响应头是服务器给客户端的 "额外信息"(比如自定义头 name: beifan),可以用 headers 参数设置:

python 复制代码
from django.http import HttpResponseNotFound
# 用 headers 传字典,自定义响应头
HttpResponseNotFound(html, headers={
    "name": "beifan"  # 客户端能拿到这个头~
})
  • 响应头是键值对,客户端(比如浏览器、Postman)可以读取这些信息,做特殊处理(比如前端根据头信息渲染不同内容)~

3. 设置 Cookies 🍪

Cookies 是服务器种在客户端的 "小饼干",用来记录状态(比如登录态、偏好设置)。Django 里分两步:

步骤 1:创建响应对象
python 复制代码
from django.http import HttpResponseNotFound
resp = HttpResponseNotFound(html)
步骤 2:种饼干!
python 复制代码
# 设置 Cookie:name=beifan,客户端下次请求会带着它
resp.set_cookie("name", "beifan")
return resp

视图必须要有返回值的!返回响应对象实例

客户端收到的响应头长这样:
python 复制代码
'Set-Cookie': 'name=beifan; Path=/; ...'

cookie很长 我们要是自定义要写好多 所以直接传参让set_cookie帮助我们生成

  • 这串内容是服务器告诉客户端:"把 name=beifan 存在 Cookie 里,下次请求带上~"
  • 客户端(浏览器)会自动保存 Cookie,下次发请求时,在请求头里带 Cookie: name=beifan,服务器就能认出 "老用户" 啦~

4. 生成 JSON 响应 📦

前后端交互常用 JSON 格式,Django 有 JsonResponse 帮我们简化流程:

传统方式(手动转 JSON)
python 复制代码
import json
from django.http import HttpResponse
data = {'num': num}
# 手动转 JSON 字符串 + 设置响应头
html = json.dumps(data)
return HttpResponse(html, content_type='application/json')
JsonResponse(偷懒神器)
python 复制代码
from django.http import JsonResponse
# 直接传字典,自动转 JSON + 设置响应头
return JsonResponse({'num': num})
  • JsonResponse 会帮你做两件事:
    1. 把字典转成 JSON 字符串(json.dumps 的活)。
    2. 设置响应头 Content-Type: application/json(告诉客户端 "这是 JSON 数据")。
  • 前端拿到响应后,直接 JSON.parse 就能用,超方便~

5. 生成重定向 🚀

重定向是服务器告诉客户端:"你要的资源不在这,去新地址找~",常用场景:登录后跳转到首页、旧链接换新地址。

临时重定向(302)
python 复制代码
from django.http import HttpResponseRedirect
# 告诉客户端:临时去百度,下次可能换地址
return HttpResponseRedirect("https://baidu.com")
  • 状态码 302,客户端下次请求可能还会走原来的地址(比如 "页面临时搬家,过几天搬回来")。
永久重定向(301)
python 复制代码
from django.http import HttpResponsePermanentRedirect
# 告诉客户端:永久去百度,以后别来旧地址了
return HttpResponsePermanentRedirect("https://baidu.com")
  • 状态码 301,客户端会记住 "旧地址失效了,以后直接访问新地址"(比如 "网站域名更换,永久迁移")。

总结时间 ⏰

这 5 个知识点,都是 Django 响应的 "常用招式":

  • 状态码:告诉客户端请求结果(成功 / 失败 / 跳转)。
  • 响应头:传额外信息,比如自定义头、Cookies。
  • Cookies:种在客户端的小饼干,记录状态。
  • JSON 响应:前后端数据交互的标准格式。
  • 重定向:让客户端去新地址找资源。

掌握这些,就能灵活控制服务器给客户端的响应啦~ 下次写 Django 视图,就可以按需选对应的 "响应招式",轻松实现各种需求~ ✨

小练习🐱‍🏍

1. submit 视图函数
python 复制代码
def submit(request: HttpRequest):
    # 打印请求体内容,用于调试,查看客户端发送的原始数据
    print("submit", request.body)  
    # 判断请求的方法是否为 POST(表单提交、Ajax  POST 等常用)
    if request.method == 'POST':  
        # 从 POST 请求数据中获取名为 "text" 的参数值,若不存在则返回 None
        text = request.POST.get("text")  
        # 如果获取到的 text 有内容(非空)
        if text:  
            # 重定向到 result 视图对应的 URL,参数拼接需注意规范,这里简单示例
            return HttpResponseRedirect('http://127.0.0.1:8000/beifan/result')  
        else:
            # 如果 text 为空,暂时不做额外处理,pass 表示跳过
            pass  
    # 打开 submit.html 文件(需确保文件路径正确),以 utf-8 编码读取内容
    html = open('submit.html', encoding="utf-8").read()  
    # 将读取的 HTML 内容作为响应体,返回给客户端,通常用于展示页面
    return HttpResponse(html)  
  • 作用 :主要处理客户端对 submit 路径的请求。GET 请求时返回 submit.html 页面用于展示(比如表单页面);POST 请求时尝试获取表单里的 text 字段,若有内容就重定向到 result 视图,用于模拟 "提交内容后跳转结果页" 的流程,常配合表单提交场景(如评论提交、数据录入后跳转反馈页 )。
2. result 视图函数
python 复制代码
def result(request):
    # 打印请求体内容,调试用,查看客户端请求该视图时发送的原始数据
    print("result", request.body)  
    # 打开 result.html 文件(需确保路径正确),以 utf-8 编码读取内容
    html = open('result.html', encoding="utf-8").read()  
    # 将读取的 HTML 内容作为响应体返回,用于展示结果页面(比如评论提交成功提示页)
    return HttpResponse(html)  
  • 作用 :处理客户端对 result 路径的请求,一般是在 submit 视图重定向过来后,返回 result.html 页面,用于展示提交后的结果(如提示评论已提交、展示数据处理结果等 ),是流程里 "提交 - 跳转 - 展示结果" 的最后一环。

这两段代码实现了一个简单的 "表单提交(或模拟提交)- 重定向 - 展示结果" 的基础流程,可用于搭建类似评论提交、信息录入并反馈结果的功能页面,不过实际项目中还需完善错误处理(如文件不存在、重定向 URL 拼接规则、POST 数据校验等 )。

什么情况下使用后端重定向什么时候前端重定向?😎

🧩 先搞懂两个 "工具人"

  1. 后端重定向 :就是你代码里的 HttpResponseRedirect(...)

    → 作用:服务器直接对浏览器说:"别在这待着了,快去这个新地址!" 🌐→🚀

  2. 前端 Axios 重定向 :前端用 Axios 发消息给服务器后,自己跳走

    → 作用:浏览器收到服务器回复后,自己对自己说:"服务器让我走啦,我去新地址咯!" 📩→🏃

🔍 什么时候必须喊 "后端重定向" 来干活?

当用户用 "传统表单" 提交数据时 → 必用后端重定向!

👉 什么是 "传统表单"?

就是前端页面长这样(你不用写,前端写):

html 复制代码
<form action="/submit" method="post">
  <input name="text" type="text"> <!-- 输入框 -->
  <button type="submit">提交</button> <!-- 提交按钮 -->
</form>

用户点 "提交" 后,浏览器会整个页面刷新 ,像 "重启" 一样把数据发给你的 submit 函数。

👉 为啥必须用后端重定向?

因为页面都 "重启" 了,只有服务器能指挥它 "重启后去哪"。就像你换工作,必须新公司(服务器)发 offer(重定向指令),你才知道去新地方~

👉 对应你的代码:

你的代码里,submit.html 很可能就是这个 "传统表单" 页面。所以当 text 有内容时,用 HttpResponseRedirect 让浏览器跳去结果页,完全正确! ✅

🔍 什么时候必须喊 "前端 Axios" 来干活?

当用户用 "不刷新页面" 的方式提交数据时 → 必用前端重定向!

👉 什么是 "不刷新页面" 提交?

就是用户点按钮后,页面不动(不闪、不重启),数据 "偷偷摸摸" 发给服务器。前端会写这样的代码(你不用关心,了解即可):

javascript 复制代码
// 前端代码(假装是按钮点击后执行)
let text = 输入框里的内容;
// 用Axios发消息给后端的/submit
Axios.post("/submit", {text: text}).then(回复 => {
  // 收到服务器说"ok"后,自己跳走
  window.location.href = "http://127.0.0.1:8000/beifan/result";
});

👉 为啥必须用前端重定向?

因为页面没 "重启",服务器喊 "去新地址" 它听不见!就像你在办公室坐着(页面没刷新),老板(服务器)远程发消息让你去会议室,必须你自己站起来走(前端自己跳转)~

👉 这时候你的代码要改吗?

要!不能用 HttpResponseRedirect 了,得告诉前端 "可以跳了":

python 复制代码
if text:  
    # 换成这个:告诉前端"成功啦,你自己跳吧"
    return JsonResponse({"状态": "成功"})  

📝 终极判断公式

看用户提交后页面会不会 "闪一下":

  • 会闪(传统表单)→ 用后端重定向(你现在的代码)
  • 不闪(偷偷提交)→ 用前端 Axios 重定向(改后端代码为返回状态)

就这么简单!😉 代码目前适配 "会闪" 的情况,完全没问题~

点前端的submit提交按钮为什么会引起页面刷新,为什么可以让服务器做出响应啊

🥳 这个问题超基础也超重要!

为啥点 submit 按钮会让页面 "闪一下"(刷新)?

因为 <button type="submit"> 是 HTML 里的 "特殊按钮",它天生就带着一个 "祖传使命":
触发表单的 "默认提交行为" → 也就是让浏览器把表单数据打包,然后重新加载整个页面,把数据发给服务器~

就像你寄快递:

  • 表单里的输入框 = 快递盒里的东西 📦
  • submit 按钮 = 你喊 "快递员快来取件" 📣
  • 页面刷新 = 快递员把盒子拿走,同时给你换一个新的页面(服务器发回来的) 🔄
👉 第一步:前端 "拨号"(告诉服务器地址)

前端的表单标签里,早就写好了 "要把数据发给谁":

html 复制代码
<form action="/submit" method="post"> 
  <!-- action="/submit" → 数据发给服务器的/submit地址 -->
  <!-- method="post" → 用POST方式发(类似打电话的"加密线路") -->
  <input name="text">
  <button type="submit">提交</button>
</form>

就像你打电话前,先输好了对方的号码(/submit)~

👉 第二步:浏览器 "传声"(打包发送数据)

你点 submit 后:

  • 浏览器会把输入框里的内容(比如text的值)打包成 "数据包裹" 📦
  • 按照action地址,通过POST方式,发给你的 Django 服务器 🚀
👉 第三步:服务器 "接电话"(处理并回复)

你的 Django 后端早就 "守在电话旁" 了:

  • urls.py里配置了/submit地址对应submit函数 → 相当于 "听到铃声,接起电话" 📞
  • submit函数里的request.method == 'POST'会 "识别来电",然后用request.POST.get("text")取出数据 → 相当于 "听对方说话,记下来" 📝
  • 最后返回HttpResponse或重定向 → 相当于 "挂电话前,说一句回复" 💬
👉 第四步:浏览器 "听回复"(刷新显示新内容)

服务器回复后:

  • 浏览器会刷新页面,显示服务器发回来的内容(可能是新页面,也可能是重定向后的地址) → 相当于 "挂了电话,看对方发来的短信" 📱

为什么点击button会触发打包数据传给服务器呢

<button>的 "身份标签" 决定了它的行为

<button>按钮有个关键属性叫type,就像它的 "工作证":

  • type="submit"时(这是默认值,就算不写也会生效!)→ 它就成了 "提交专用按钮" 📤
  • type="button"时 → 它只是个 "普通按钮",点了啥也不会自动提交 🚫

它和<form>标签是 "最佳搭档"

单独一个<button type="submit">啥也干不了,必须 "抱大腿"------ 放在<form>标签里面才行!

<form>标签就像一个 "数据收集箱" 📦,它会:

  • 通过action属性记住 "数据要发给谁"(比如action="/submit"就是发给服务器的/submit地址)
  • 通过method属性记住 "用什么方式发"(比如method="post"

这一切都是 HTML 规定好的 "自动流程",不用写任何额外代码,浏览器会帮你完成从 "点击" 到 "发送" 的所有步骤~

一句话总结:

因为这个按钮是type="submit",并且 "住在"<form>标签里,所以点击时会触发<form>的 "自动打包 + 发送" 功能,就像按了开关一样自然~ 🔌→📤

实战: 接收 JSON 参数返回 JSON 和 接收表单参数重定向🐱‍🐉

需求 1:接收 JSON 参数,返回 JSON 内容

myapp/views.py 中编写视图:

python 复制代码
from django.http import JsonResponse, HttpResponse
import json

def receive_json(request):
    # 处理 POST 请求(通常客户端发 JSON 用 POST )
    if request.method == 'POST':  
        try:
            # 解析请求体的 JSON 数据,request.body 是原始字节数据,先转字符串再 loads
            data = json.loads(request.body.decode('utf-8'))  
            # 简单处理:把收到的 JSON 数据原样返回(也可按需加工,比如新增字段 )
            return JsonResponse(data)  
        except json.JSONDecodeError:
            # 如果解析失败,返回 400 错误,告知客户端数据格式有问题
            return HttpResponse("Invalid JSON data", status=400)  
    # 非 POST 请求,返回提示(也可根据需求调整,比如支持 GET 传 JSON 字符串,但 POST 更常用 )
    return HttpResponse("Only POST requests with JSON data are allowed", status=405)  

接着配置路由(关联视图 )

测试方式

可用 curl 命令测试(终端执行 ):

bash 复制代码
# 发送 JSON 数据,测试接收和返回
curl -X POST -H "Content-Type: application/json" -d '{"name": "beifan", "age": 18}' http://127.0.0.1:8000/receive-json/

或用 Postman 等工具,发送 POST 请求,Content-Type 设为 application/json,请求体填 JSON 内容(如 {"name": "beifan"} ),查看响应是否返回相同 JSON 数据。

需求 2:接收表单参数,重定向到结果页面

myapp/views.py 中补充视图:

python 复制代码
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render

def submit_form(request):
    # 处理 GET 请求,返回表单页面(这里简单用 HttpResponse 模拟,实际常用 render 加载 HTML 文件 )
    if request.method == 'GET':  
        return HttpResponse('''
            <html>
                <body>
                    <form method="POST" action="/submit-form/">
                        <input type="text" name="username" placeholder="用户名">
                        <input type="submit" value="提交">
                    </form>
                </body>
            </html>
        ''')
    # 处理 POST 请求(表单提交 )
    elif request.method == 'POST':  
        # 获取表单里的 username 字段值,若不存在则为 None
        username = request.POST.get('username')  
        if username:
            # 重定向到结果页面,可把参数拼接到 URL(简单示例,也可用其他方式传参 )
            return HttpResponseRedirect(f'/result/?username={username}')  
        else:
            # 若用户名为空,返回提示(实际可优化,比如留在表单页提示填写 )
            return HttpResponse("Username can't be empty", status=400)  

def result_page(request):
    # 从请求中获取参数(重定向带过来的 )
    username = request.GET.get('username')  
    # 简单返回结果页面,展示用户名(实际常用 render 加载 HTML 文件渲染 )
    return HttpResponse(f'Hello, {username}! Submission successful.')  

Django 里的JsonResponse类

JsonResponse是 Django 专门用来返回JSON 格式数据的工具类,长得就像一个 "带 JSON 包装纸的响应包裹" 📦,专门给前端(比如用 Axios 发请求的场景)送数据~

🧐 它长什么样?(基本用法)

python 复制代码
from django.http import JsonResponse

def my_view(request):
    # 准备要返回的数据(字典形式)
    data = {
        "status": "success",  ✅ 状态标识
        "message": "操作成功啦~",  💬 提示信息
        "result": {"name": "小明", "age": 18}  📊 具体数据
    }
    # 用JsonResponse包装数据并返回
    return JsonResponse(data)

✨ 它的 "特殊技能"

自动打包成 JSON 🧰

不用你手动把字典转成 JSON 字符串,JsonResponse会自动帮你做这件事~ 上面的代码返回给前端的会是这样的 JSON:

复制代码
{"status": "success", "message": "操作成功啦~", "result": {"name": "小明", "age": 18}}

自带正确的 "身份标识" 🏷️

会自动在响应头里加上Content-Type: application/json,告诉前端:"我送的是 JSON 数据哦,快用 JSON 的方式解析我~"

可以定制行为 ⚙️

如果想返回列表(不是字典),需要加safe=False

python 复制代码
return JsonResponse([1, 2, 3], safe=False)  📋 列表数据专用

可以指定编码:

python 复制代码
return JsonResponse(data, json_dumps_params={'ensure_ascii': False})  🌐 支持中文不转义

🆚 和HttpResponse的区别

  • HttpResponse是 "万能包裹" 📦,可以返回 HTML、文本等任何内容,但返回 JSON 需要手动处理(比如用json.dumps())。
  • JsonResponse是 "JSON 专用包裹" ✨,专为返回 JSON 设计,更方便、更规范~

简单说,JsonResponse就像一个 "自动打包机",把你的 Python 字典 / 列表快速变成前端能看懂的 JSON 数据,超适合前后端用 Ajax(比如 Axios)通信时使用哦~ 😎

json.loads() 是把 "JSON 格式的字符串(像python的字典一样)" 转成 Python 数据

而 json.load() 直接处理 "JSON 文件"

📄 vs 📜

相关推荐
mCell22 分钟前
告别轮询!深度剖析 WebSocket:全双工实时通信原理与实战
后端·websocket·http
2025年一定要上岸2 小时前
【Django】-10- 单元测试和集成测试(下)
数据库·后端·python·单元测试·django·集成测试
i-阿松!3 小时前
Django + Vue 项目部署(1panel + openresty)
vue.js·django·openresty
2025年一定要上岸5 小时前
【Django】-7- 实现注册功能
后端·python·django
小王子102420 小时前
Django集成图片验证码功能:基于django-simple-captcha实现
django·验证码·django-simple-captcha
Q_Q5110082851 天前
python的驾校培训预约管理系统
开发语言·python·django·flask·node.js·php
2025年一定要上岸1 天前
【Django】-9- 单元测试和集成测试(上)
单元测试·django·集成测试