目录
[GET、POST、PUT、DELETE 到底分别是干什么的](#GET、POST、PUT、DELETE 到底分别是干什么的)
[1. GET:获取数据](#1. GET:获取数据)
[浏览器为什么最容易访问 GET](#浏览器为什么最容易访问 GET)
[2. POST:创建数据](#2. POST:创建数据)
[为什么创建一般用 POST,不用 GET](#为什么创建一般用 POST,不用 GET)
[3. PUT:整体更新数据](#3. PUT:整体更新数据)
[FastAPI 例子](#FastAPI 例子)
[PUT 的重点](#PUT 的重点)
[4. PATCH:部分更新数据](#4. PATCH:部分更新数据)
[PUT 和 PATCH 的区别](#PUT 和 PATCH 的区别)
[5. DELETE:删除数据](#5. DELETE:删除数据)
[6. 一套完整的 REST 风格接口长什么样](#6. 一套完整的 REST 风格接口长什么样)
[7. 什么叫"不要把动作乱塞进路径里"](#7. 什么叫“不要把动作乱塞进路径里”)
[8. 为什么同一个路径可以对应不同方法](#8. 为什么同一个路径可以对应不同方法)
[9. 一个完整示例:商品模块](#9. 一个完整示例:商品模块)
[10. 在浏览器、Swagger、Postman 里分别怎么测](#10. 在浏览器、Swagger、Postman 里分别怎么测)
[Swagger 文档](#Swagger 文档)
[Postman / Apifox](#Postman / Apifox)
[11. 什么时候该用哪一个](#11. 什么时候该用哪一个)
[用 GET 的场景](#用 GET 的场景)
[用 POST 的场景](#用 POST 的场景)
[用 PUT 的场景](#用 PUT 的场景)
[用 PATCH 的场景](#用 PATCH 的场景)
[用 DELETE 的场景](#用 DELETE 的场景)
[12. Agent 项目里怎么映射这些方法](#12. Agent 项目里怎么映射这些方法)
[13. 一个常见误区:POST 不只是"创建"](#13. 一个常见误区:POST 不只是“创建”)
[14. 最后给你一个最好记的口诀](#14. 最后给你一个最好记的口诀)
GET、POST、PUT、DELETE 到底分别是干什么的
你可以先用一个很接地气的类比:
假设你有一个"商品系统"。
-
GET:查看商品
-
POST:新建商品
-
PUT:整体修改商品
-
DELETE:删除商品
再补一个你之后一定会遇到的:
- PATCH:部分修改商品
1. GET:获取数据
GET 最核心的语义是:
从服务器读取资源,不应该用来修改数据
比如:
-
获取商品列表
-
获取某个商品详情
-
搜索用户
-
查询订单状态
例子
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/items")
async def list_items():
return [
{"id": 1, "name": "键盘"},
{"id": 2, "name": "鼠标"}
]
@app.get("/items/{item_id}")
async def get_item(item_id: int):
return {"id": item_id, "name": "键盘"}
这里:
-
GET /items:查列表 -
GET /items/1:查单个
浏览器为什么最容易访问 GET
因为你在浏览器地址栏里输入网址,本质上默认发的就是 GET 请求。
所以 GET 是最容易直接测试的。
2. POST:创建数据
POST 最常见的语义是:
向服务器提交数据,通常用于新建资源
比如:
-
创建用户
-
创建商品
-
提交聊天消息
-
创建订单
-
上传表单
例子
python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ItemCreate(BaseModel):
name: str
price: float
@app.post("/items")
async def create_item(item: ItemCreate):
return {
"message": "创建成功",
"item": item
}
请求可以是:
{
"name": "键盘",
"price": 199.0
}
为什么创建一般用 POST,不用 GET
因为 GET 的语义是"读取",而创建会改变服务器状态。
如果你用 GET 去创建数据,那接口设计就会开始发癫:
python
@app.get("/create-item")
async def create_item():
...
这 technically 也许能跑,但语义上非常不规范。
别人一看会想:"你这是接口,还是惊悚片伏笔?"
3. PUT:整体更新数据
PUT 的核心语义通常是:
用新的完整数据替换旧资源
注意关键词:完整替换
比如你有一个商品:
{
"id": 1,
"name": "键盘",
"price": 199.0,
"stock": 10
}
如果你用 PUT 更新它,通常意味着你要提供这整个资源的新版本,而不是只改一点点。
FastAPI 例子
python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ItemUpdate(BaseModel):
name: str
price: float
stock: int
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: ItemUpdate):
return {
"message": "整体更新成功",
"item_id": item_id,
"new_item": item
}
请求体:
{
"name": "机械键盘",
"price": 299.0,
"stock": 8
}
PUT 的重点
它更像:
"把这条记录按我给你的这份完整内容重写一遍"
所以很多规范里会把 PUT 理解为"整体替换"。
4. PATCH:部分更新数据
这个你一定要顺手一起学,因为实际项目里它非常常见。
PATCH 的核心语义是:
只修改资源的一部分字段
比如你只想把价格从 199 改成 299,不想把整个商品都重传一遍。
例子
python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ItemPatch(BaseModel):
name: str | None = None
price: float | None = None
stock: int | None = None
@app.patch("/items/{item_id}")
async def patch_item(item_id: int, item: ItemPatch):
return {
"message": "部分更新成功",
"item_id": item_id,
"changed_fields": item.model_dump(exclude_none=True)
}
请求体可能是:
{
"price": 299.0
}
PUT 和 PATCH 的区别
你可以这样记:
-
PUT:整套换掉
-
PATCH:只修一点
这俩在很多项目里都会同时存在。
5. DELETE:删除数据
DELETE 的语义最直接:
删除某个资源
比如:
-
删除商品
-
删除用户
-
删除会话
-
删除任务
例子
python
from fastapi import FastAPI
app = FastAPI()
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
return {
"message": "删除成功",
"item_id": item_id
}
调用:
DELETE /items/1
意思就是删除 id=1 的商品。
6. 一套完整的 REST 风格接口长什么样
假设你做一个商品模块,最常见的设计会像这样:
| 操作 | HTTP 方法 | 路径 | 含义 |
|---|---|---|---|
| 获取商品列表 | GET | /items |
查所有商品 |
| 获取单个商品 | GET | /items/{item_id} |
查某个商品 |
| 创建商品 | POST | /items |
新建商品 |
| 整体更新商品 | PUT | /items/{item_id} |
全量替换商品 |
| 部分更新商品 | PATCH | /items/{item_id} |
局部修改商品 |
| 删除商品 | DELETE | /items/{item_id} |
删除商品 |
这就是非常典型的 REST 风格设计。
你可以发现一个规律:
-
路径表示资源
-
HTTP 方法表示动作
而不是把动作写进路径里。
7. 什么叫"不要把动作乱塞进路径里"
初学者很容易这样设计:
/getItems
/createItem
/updateItem
/deleteItem
这个当然能用,但不够规范。
更推荐的是:
GET /items
POST /items
PUT /items/{item_id}
DELETE /items/{item_id}
原因很简单:
-
路径表示"你在操作谁"
-
方法表示"你要干什么"
也就是说:
-
/items是资源 -
GET/POST/PUT/DELETE是动作
这样接口会更统一,也更容易扩展。
8. 为什么同一个路径可以对应不同方法
比如这两个:
python
@app.get("/items")
async def list_items():
...
@app.post("/items")
async def create_item():
...
路径都是 /items,但不会冲突。
因为 FastAPI 区分路由时,不只是看路径,还看:
-
路径
-
HTTP 方法
所以:
-
GET /items→ 查列表 -
POST /items→ 创建数据
这俩是不同的接口。
9. 一个完整示例:商品模块
我给你写一个稍微完整点的版本,你一看就会更顺。
python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# 模拟数据库
items_db = {
1: {"id": 1, "name": "键盘", "price": 199.0, "stock": 10},
2: {"id": 2, "name": "鼠标", "price": 99.0, "stock": 20},
}
class ItemCreate(BaseModel):
name: str
price: float
stock: int
class ItemUpdate(BaseModel):
name: str
price: float
stock: int
class ItemPatch(BaseModel):
name: str | None = None
price: float | None = None
stock: int | None = None
@app.get("/items")
async def list_items():
return list(items_db.values())
@app.get("/items/{item_id}")
async def get_item(item_id: int):
return items_db.get(item_id, {"error": "商品不存在"})
@app.post("/items")
async def create_item(item: ItemCreate):
new_id = max(items_db.keys()) + 1
new_item = {"id": new_id, **item.model_dump()}
items_db[new_id] = new_item
return new_item
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: ItemUpdate):
if item_id not in items_db:
return {"error": "商品不存在"}
items_db[item_id] = {"id": item_id, **item.model_dump()}
return items_db[item_id]
@app.patch("/items/{item_id}")
async def patch_item(item_id: int, item: ItemPatch):
if item_id not in items_db:
return {"error": "商品不存在"}
update_data = item.model_dump(exclude_none=True)
items_db[item_id].update(update_data)
return items_db[item_id]
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
if item_id not in items_db:
return {"error": "商品不存在"}
deleted = items_db.pop(item_id)
return {"message": "删除成功", "deleted_item": deleted}
这个例子基本把 CRUD 串起来了:
-
Create → POST
-
Read → GET
-
Update → PUT/PATCH
-
Delete → DELETE
10. 在浏览器、Swagger、Postman 里分别怎么测
浏览器地址栏
适合测 GET:
-
http://127.0.0.1:8000/items -
http://127.0.0.1:8000/items/1
因为浏览器默认 GET。
Swagger 文档
FastAPI 启动后访问:
http://127.0.0.1:8000/docs
这里最适合测:
-
GET
-
POST
-
PUT
-
PATCH
-
DELETE
因为它能直接选方法、填参数、发请求。
Postman / Apifox
适合做更真实的接口调试,尤其是:
-
带 JSON body 的 POST/PUT/PATCH
-
带 Header 的请求
-
带 Token 的认证接口
11. 什么时候该用哪一个
这个你一定要形成直觉。
用 GET 的场景
你只是"看"数据,不改服务器状态。
比如:
-
获取聊天记录
-
查看任务列表
-
查询某个用户资料
-
搜索商品
用 POST 的场景
你在"提交新数据"或触发一个创建型动作。
比如:
-
新建会话
-
发送一条聊天消息
-
创建订单
-
上传文件
-
提交表单
用 PUT 的场景
你要把某个对象整体更新。
比如:
-
用户资料整条替换
-
商品完整信息覆盖更新
用 PATCH 的场景
你只改少数字段。
比如:
-
只修改昵称
-
只改任务状态
-
只改价格
-
只改某条记录的备注
用 DELETE 的场景
你要删除某个资源。
比如:
-
删除会话
-
删除任务
-
删除商品
-
删除评论
12. Agent 项目里怎么映射这些方法
你现在在学 agent 应用,这里我顺手给你对应一下,会更有感觉。
假设你有一个聊天系统:
获取会话列表
python
@app.get("/conversations")
获取某个会话详情
python
@app.get("/conversations/{conversation_id}")
创建新会话
python
@app.post("/conversations")
发送用户消息
python
@app.post("/conversations/{conversation_id}/messages")
修改会话标题
python
@app.patch("/conversations/{conversation_id}")
删除会话
python
@app.delete("/conversations/{conversation_id}")
你会发现,思路是一样的:
-
路径写资源
-
方法写动作
这就是接口设计的骨架。
13. 一个常见误区:POST 不只是"创建"
这个点我得顺手拧正一下。
虽然最典型的 POST 是"创建资源",但在实际项目里,POST 也常用来做:
-
登录
-
执行某个复杂动作
-
提交推理请求
-
调用 AI 对话生成
-
上传和处理文件
比如:
python
@app.post("/chat")
async def chat(req: ChatRequest):
...
因为"对话生成"不太像简单的资源读取,也不一定适合 PUT/DELETE,所以 POST 很常见。
也就是说:
-
GET 主要是读
-
POST 最常见是创建,也常用于"提交一个动作"
-
PUT/PATCH 是更新
-
DELETE 是删除
14. 最后给你一个最好记的口诀
你可以先记成这套:
-
GET:拿数据
-
POST:交数据 / 建数据
-
PUT:整条改
-
PATCH:局部改
-
DELETE:删数据
再进一层理解就是:
-
路径表示资源
-
方法表示操作
-
不要把动作乱写进路径
-
让接口设计尽量统一