01、FastApi快速入门一:基础语法

FastApi快速入门一:基础语法

一、简介

FastAPI 是一个现代、高性能的 Python Web 框架,用于构建 API。
它基于Starlette(异步 Web 框架)和Pydantic(数据验证库),结合了异步编程和类型提示,兼顾开发效率与运行性能。

·使用 Uvicorn(ASGI服务器),支持高并发请求。
·FastAPI:~3000 请求/秒(异步,轻量)
·Flask:~1000 请求/秒(同步,受WSGI 限制)
·Django:~800 请求/秒(同步,ORM 和中间件开销较大)
·支持 async/await 语法,适合高并发场景(如实时聊天、流处理)
·比传统同步框架(如 Flask)更适合现代 Web 应用

二、环境搭建

##创建虚拟环境
conda create -n fastapi_env python=3.13.5

##激活虚拟环境
conda activate fastapi_env

##退出虚拟环境
conda deactivate
##安装FastAPI及其依赖

##在虚拟环境中安装FastAPI (安装的是最新的版本)
pip install "fastapi[standard]"

##指定版本安装
pip install fastapi==0.115.12
pip install uvicorn==0.34.2

三、快速入门

1、第一个程序与启动

from typing import Union;

from fastapi import FastAPI;

app = FastAPI();

"""
1、普通get
"""
@app.get("/hello")
async def hello():
    return {"message": "Hello World"};

"""
2、带参get
eg: localhost:8000/query/123?item_name=123
"""
@app.get("/query/{item_id}")
def read_item(item_id: int, item_name: Union[str, None] = None):
    return {"item_id": item_id, "item_name": item_name};
##启动服务

##第一种方式
uvicorn filename:app_name --reload   ##加上--reload后,修改代码后会自动重新加载

##第二种方式
fastapi dev filename.py

##第三种方式
python filename.py
#需要在文件中加上如下代码
import uvicorn;
if __name__ == "__main__":
	uvicorn.run("filename:app_name",host="127.0.0.1",port=8000,reload=True);  #加reload必须这种写法
    或
	uvicorn.run(app_name,host="127.0.0.1",port=8000)
##查看文档

http://127.0.0.1/docs
http://127.0.0.1/redoc

2、路径参数

"""
路径参数
"""
import uvicorn
from fastapi import FastAPI;

app = FastAPI();

## 路径参数-->默认接受的参数类型是str
@app.get("/params1/{id}")
def read_params_1(id):
    return {"id": id};

## 接受多个路径参数
@app.get("/params2/{id}/{name}")
def read_params_2(id, name):
    return {"id": id, "name": name};


## 路径参数-->指定参数类型
@app.get("/params3/{id}/{name}")
def read_params_3(id: int, name: str):
    return {"id": id, "name": name};


##启动服务
if __name__ == '__main__':
    uvicorn.run("01_pathParam:app", host="127.0.0.1", port=8000, reload=True);

3、查询参数

##语法
url ? 参数1=值 & 参数2=值
"""
查询参数
"""
import uvicorn;
from fastapi import FastAPI;

app = FastAPI();


# 查询参数
@app.get("/queryParams1")
def query_params_1(pages: int, limit: int):
    return {"pages": pages, "limit": limit};


# 查询参数-->默认参数是可选的
@app.get("/queryParams2")
def query_params_2(pages: int, limit: int = 10):
    return {"pages": pages, "limit": limit};


# 查询参数-->路径参数与参训参数混用
@app.get("/queryParams3/{pages}")
def query_params_3(pages: int, limit: int = 10):
    return {"pages": pages, "limit": limit};


if __name__ == "__main__":
    uvicorn.run("02_queryParam:app", host="127.0.0.1", port=8000, reload=True);

4、请求体

"""
查询参数-->请求体参数
"""
import uvicorn
from fastapi import FastAPI;
from pydantic import BaseModel;


class UserClass(BaseModel):
    username: str;
    password: str;
    gender: str | None;
    age: int = 20;


app = FastAPI();


# 字典类-->请求体参数
@app.post("/queryBody1")
def query_body_1(userDict: dict):
    return userDict;


# 类-->请求体参数
@app.post("/queryBody2")
def query_body_2(userClass: UserClass):      # 指定 对应的类
    return userClass;

if __name__ == "__main__":
    uvicorn.run("03_queryBody:app", host="0.0.0.0", port=8000, reload=True);

5、请求参数验证

5.1、类型注解方式
"""
请求参数验证:
    类型注解方式

"""
from typing import Union,Optional,List;
import uvicorn;
from fastapi import FastAPI;

app = FastAPI();

# 路径参数验证——指定参数是字符串类型
@app.get("/paramsValid1/{param}")
def paramValid1(param: str):
    return param;

# 路径参数验证——指定参数是字符串或整数类型,默认值为10
@app.get("/paramsValid2/{param}")
def paramsValid2(param: Union[str, int] = 10):
    return param;

# 路径参数验证——指定参数是可选的字符串类型,默认值为None
@app.get("/paramsValid3")
def paramsValid3(param: Optional[str] = None):
    return param;



if __name__ == "__main__":
    uvicorn.run("04_paramsValid:app",host="127.0.0.1",port=8000,reload=True);
5.2、Query方式
参数名类型默认值说明示例
default / ...AnyNone设置参数的默认值。使用 ... 表示该参数为必填项。param: int = Query(10) param: int = Query(...)(必填)
aliasstrNone指定参数在 URL 中使用的别名(可用于含特殊字符或不符合 Python 命名规范的参数名)。field_name: str = Query(None, alias="field-name")/items?field-name=value
titlestrNone为参数设置标题,主要用于 API 文档(如 Swagger)显示。param: str = Query(None, title="User ID")
descriptionstrNone描述该参数用途,显示在 API 文档中。param: str = Query(None, description="用户名,用于搜索")
deprecatedboolFalse标记该参数已弃用,在文档中显示警告。param: str = Query(None, deprecated=True)
include_in_schemaboolTrue是否将该参数包含在生成的 OpenAPI 文档中。设为 False 可隐藏参数。debug: bool = Query(False, include_in_schema=False)

数字验证 int /float

参数名类型默认值说明示例
gtfloatNone值必须大于指定值(greater than)age: int = Query(..., gt=0)
gefloatNone值必须大于等于指定值(greater than or equal)age: int = Query(1, ge=1)
ltfloatNone值必须小于指定值(less than)score: float = Query(None, lt=100.0)
lefloatNone值必须小于等于指定值score: float = Query(None, le=100.0)

字符串验证

参数名类型默认值说明示例
min_lengthintNone字符串最小长度name: str = Query(..., min_length=3)
max_lengthintNone字符串最大长度name: str = Query("abc", max_length=50)
regexstrNone字符串必须匹配正则表达式code: str = Query(..., regex=r"^\d{3}-\d{2}$")

列表/多个值验证

参数名类型默认值说明示例
min_itemsintNone列表最小项数(需配合 List[T] 使用)ids: list[int] = Query(None, min_items=1)
max_itemsintNone列表最大项数tags: list[str] = Query(None, max_items=5)
"""
参数验证
    query方式
"""
import uvicorn;
from fastapi import FastAPI,Query;

app =FastAPI();

# 验证query参数param是否存在,不存在则返回默认值123
@app.get("/paramsValid1")
def paramsValid1(param: str = Query(123)):
    return param;

# 验证query参数param是否存在,不存在则抛出异常 (...表示必须存在)
@app.get("/paramsValid2")
def paramsValid2(param: str = Query(...)):
    return param;

# 验证长度是否在3-5之间
@app.get("/paramsValid3")
def paramsValid3(param: str = Query(...,min_length=3,max_length=5)):
    return param;

# 验证大于10 小于20
@app.get("/paramsValid4")
def paramsValid4(param: int = Query(...,gt=10,lt=20)):
    return param;

# 前端传参数的名称是id,后端接收参数的名称是param
@app.get("/paramsValid5")
def paramsValid5(param: int = Query(...,alias="id")):
    return param;

if __name__=="__main__":
    uvicorn.run("05_paramsValid:app",host="127.0.0.1",port=8000,reload=True);
5.3、path方式
具体参数雷同query
"""
参数验证
    query方式
"""
import uvicorn;
from fastapi import FastAPI,Query;

app =FastAPI();

# 验证query参数param是否存在,不存在则返回默认值123
@app.get("/paramsValid1/{id}")
def paramsValid1(id: int = Path(...,lt=10,gt=20)):
    return id;

if __name__=="__main__":
    uvicorn.run("06_paramsValid:app",host="127.0.0.1",port=8000,reload=True);
5.4、field方式
具体参数雷同query和path
from fastapi import FastAPI, Body
from pydantic import BaseModel, Field
from typing import List, Optional

app = FastAPI()

class UserCreate(BaseModel):
    user_name: str = Field(
        ...,
        min_length=3,
        max_length=20,
        regex=r"^[a-zA-Z0-9_]+$",
        description="用户名,仅支持字母、数字、下划线",
        example="alice123"
    )
    age: int = Field(
        ...,
        gt=0,
        le=150,
        description="年龄,必须在1-150之间"
    )
    email: Optional[str] = Field(
        None,
        regex=r"^[^@]+@[^@]+\.[^@]+$",
        description="邮箱格式"
    )
    tags: List[str] = Field(
        None,
        min_items=1,
        max_items=5,
        description="用户标签,最多5个"
    )
    internal_key: str = Field(
        None,
        include_in_schema=False  # 不出现在文档中
    )

@app.post("/users")
def create_user(user: UserCreate = Body(...)):
    return {"user": user}

6、表单数据

使用表单需预先安装
pip install python-multipart
"""
表单数据
"""
import uvicorn
from fastapi import FastAPI, Form;
from pydantic import BaseModel

app = FastAPI();


# 单个参数--表单数据
@app.post("/login1")
def formLogin1(username: str = Form(...), password: str = Form(...)):
    return {"username": username, "password": password}

class User(BaseModel):
    username: str;
    password: str;

# 实体参数--表单数据
@app.post("/login2")
def formLogin2(user : User = Form(...)):
    return {"username": user.username, "password": user.password}


if __name__ == "__main__":
    uvicorn.run("06_formData:app", host="0.0.0.0", port=8000,reload=True);

7、异步请求

"""
异步方法
"""
import uvicorn;
from fastapi import FastAPI;

app = FastAPI();

@app.get("/login2")
async def getUserInfo():
    return {"username": "admin", "password": "123456"}

if __name__ == "__main__":
    uvicorn.run("07_asyncMethod:app", host="0.0.0.0", port=8000,reload=True);

8、文件上传

#方法一:
byte  适合小文件 10M以内 ---> 会将文件一次性加载到内存中

#方法二:
UploadFile 推荐 (大文件)
"""
文件上传1
byte 上传  适合小文件(全部加载到内存中)
uploadFile 上传
"""
import asyncio

import uvicorn;
from fastapi import FastAPI,File,UploadFile;

app = FastAPI();


##使用bytes方式上传文件会丢失文件的元数据(文件名、文件大小等)
@app.post("/upload")
def uploadFile(file: bytes = File(...)):
    contents = file.decode("utf-8");
    return {"content": contents};

@app.post("/upload2")
async def uploadFile2(file: UploadFile):
    while chunk := await file.read(1024):
        print(chunk);
    return {"filename": file.filename};



if __name__ == "__main__":
    uvicorn.run("08_fileUpload:app", host="127.0.0.1", port=8000,reload=True);

9、请求对象Request

获取用户请求信息
"""
Requet访问对象
"""
import uvicorn;
from fastapi import FastAPI, Request;

app = FastAPI();


@app.get("/getClientInfo")
async def getClientInfo(request: Request):
    """
    获取客户端用户信息
    :param request:
    :return:
    """
    return {
        "请求IP": request.client.host,
        "请求URL": request.url,
        "请求方法": request.method,
        "请求参数": request.query_params,
        "请求头": request.headers,
        "请求Cookie": request.cookies,
        "请求path_params": request.path_params,
        "user_agent": request.headers.get("user-agent")
    }


if __name__ == "__main__":
    uvicorn.run(app="09_request:app", host="127.0.0.1", port=8000, reload=True);

10、响应数据类型

10.1、JSON格式
FastAPI天然支持通过Python字典或Pydantic模型自动序列化为JSON响应
"""
响应JSON数据
"""
from typing import Union,TypeVar,Generic

import uvicorn;
from fastapi import FastAPI;
from pydantic import BaseModel;

app = FastAPI();

class Item(BaseModel):
    id: int
    name: str
    price: float

T = TypeVar('T');
class SuccessResponse(BaseModel, Generic[T]):
    code: int = 200
    msg: str = "success"
    data: Item

class ErrorResponse(BaseModel, Generic[T]):
    code: int = 400
    msg: str = "error"
    data: None = None

@app.get("/item/dict")
def getItemDict():
    """
    以字典形式返回信息
    """
    return {
        "id": 1,
        "name": "item1",
        "price": 100
    };

@app.get("/item/model1")
def getItemModel1():
    """
    以模型形式返回信息
    """
    return Item(id=2, name="item2", price=200);

@app.get("/item/model2", response_model=Item)
def getItemModel2():
    """
    以模型形式返回信息
    """
    return Item(id=2, name="item2", price=200);


@app.get("/item/model3/{item_id}", response_model=Union[SuccessResponse[Item], ErrorResponse[Item]])
def getItemModel3(item_id: int):
    """
    以模型形式返回信息
    """
    if item_id == 1:
        return SuccessResponse(code=0, msg="success",data = Item(id=2, name="item2", price=200));
    else:
        return ErrorResponse[Item](code=1, msg="error");



if __name__ == "__main__":
    uvicorn.run(app="10_response_json:app", host="127.0.0.1", port=8000, reload=True);

10.2、列表响应
用于分页查询或批量数据返回等
"""
    以列表形式返回信息
"""

import uvicorn;
from fastapi import FastAPI;
from pydantic import BaseModel;

app = FastAPI();


class Item(BaseModel):
    id: int
    name: str
    price: float
    category: str = "apple";


@app.get("/items/normalList")
def getNormalList():
    """
    以列表形式返回信息
    """
    return ["item1", "item2", "item3"];


@app.get("/items/modelList")
def getModelList():
    """
    以模型列表形式返回信息
    """
    myList = [Item(id=i, name=f"item{i}", price=i*100, category="apple" if i % 2 == 0 else "orange") for i in
              range(10)];
    return myList;


if __name__ == "__main__":
    uvicorn.run(app="11_response_list:app", host="127.0.0.1", port=8000, reload=True);

##注意:
"apple" if i % 2 == 0 else "orange"  这种写法是三元运算,不是简单的 if else

##三元运算语法:

value_if_true if condition else value_if_false

这个语法是 表达式(expression),不是语句(statement),所以它必须返回一个值,并且顺序是:
先写 满足条件时的值
再写 if 条件
然后 else
最后写 不满足条件时的值
10.3、文件响应
用于报表导出、文件下载等

文件响应的关键特点:
·内容类型:通过 Content-Type 头指定文件的 MIME 类型,
		如text/plain (txt文件) text/csv  (CSV文件)、 application/pdf  (PDF文件)、application/vnd.ms-excel  (Excel文件)

·文件内容:响应的 body包含文件的实际数据,可能是二进制(如 PDF、图片)或文本(如 CSV、JSON 文件)。


Content-Type        用于 告诉浏览器文件的类型是什么
Content-Disposition 用于 告诉浏览器如何处理响应体的内容,尤其是:是应该“在浏览器中直接显示”内容,还是“提示用户下载”为一个文件

Content-Disposition: inline    (在浏览器中直接显示内容)显示图片、PDF、HTML 文件等 
Content-Disposition: attachment; filename="filename.txt"  (提示用户将响应内容保存为一个文件)文件直接下载(如导出 Excel、PDF、ZIP 等)

文本类型

Content-Type说明
text/plain纯文本文件(.txt)
text/htmlHTML 页面
text/cssCSS 样式表
text/javascriptJavaScript 文件(现已不推荐,用 application/javascript
text/csvCSV 表格文件
text/xmlXML 数据

应用类型

Content-Type说明
application/json最常用! JSON 数据格式
application/xmlXML 数据
application/pdfPDF 文件
application/zipZIP 压缩包
application/octet-stream二进制流数据(通用下载类型,常用于未知文件)
application/xhtml+xmlXHTML 文档
application/javascriptJavaScript 文件(推荐用这个)
application/x-www-form-urlencoded表单提交默认格式(如 <form> 提交)
application/vnd.ms-excelExcel 文件(.xls)
application/vnd.openxmlformats-officedocument.spreadsheetml.sheetExcel 文件(.xlsx)
application/mswordWord 文档(.doc)
application/vnd.openxmlformats-officedocument.wordprocessingml.documentWord 文件(.docx)

表单类型

Content-Type说明
application/x-www-form-urlencoded普通表单提交,数据被编码成 key=value&key2=value2
multipart/form-data用于上传文件的表单,支持二进制数据

图片类型

Content-Type说明
image/jpegJPEG 图片(.jpg, .jpeg)
image/pngPNG 图片(.png)
image/gifGIF 动图(.gif)
image/webpWebP 格式(现代网页推荐)
image/svg+xmlSVG 矢量图
image/bmpBMP 位图
image/tiffTIFF 图像(专业用途)

音频类型

Content-Type说明
audio/mpegMP3 音频
audio/wavWAV 音频
audio/oggOgg 音频格式
audio/aacAAC 音频
audio/webmWebM 音频

视频类型

Content-Type说明
video/mp4MP4 视频
video/mpegMPEG 视频
video/oggOgg 视频
video/webmWebM 视频(HTML5 推荐)
video/quicktimeMOV 视频(苹果)
"""
文件下载
"""
import uvicorn
from fastapi import FastAPI,File,UploadFile;
from fastapi.responses import Response,FileResponse;
from starlette.responses import StreamingResponse

app = FastAPI();

@app.get("/download/txt")
def downloadText():
    """
    下载txt文件
    """
    content = b"hello World";  ##b表示字节类型的字符串
    return Response(
        content=content,
        media_type='text/plain',
        headers={"Content-Disposition": "attachment; filename=test.txt"}
    );

@app.get("/download/img")
def downloadImg():
    return FileResponse(
        path=r"D:\utils\壁纸\动漫\1.jpg",
        media_type="image/png",
        headers={"Content-Disposition": "attachment; filename=1.jpg"}
    )

"""
将大文件切成小文件  1024表示1kb
"""
def generate_chunks(file_path: str, chunk_size: int = 1024*1024*5):
    with open(file_path, "rb") as f:
        while chunk := f.read(chunk_size):
            yield chunk

@app.get("/download/pdf")
def downloadPdf():
    """
    下载pdf文件
    """
    return StreamingResponse(
        content= generate_chunks(r"G:\LearnSpace\daily-code-notes\06、Python与大模型笔记\资料\LLM Universe.pdf",1024*1024*7),
        media_type="application/pdf",
        headers={"Content-Disposition": "attachment; filename=test.pdf"}
    )


if __name__=='__main__':
    uvicorn.run(app="12_response_file:app", host="127.0.0.1", port=8000, reload=True);

##其他解读
1、  :=  海象运算符(Walrus Operator)
这是 Python 3.8+ 引入的新语法:赋值表达式,它可以在表达式中同时进行赋值和判断。

#传统写法(Python < 3.8)
while True:
    chunk = f.read(chunk_size)
    if not chunk:  # 读完了(空 bytes)
        break
    yield chunk
 
#新写法                   
while chunk := f.read(chunk_size):
    yield chunk

等价于:

先执行 f.read(chunk_size) 读取数据
把结果赋值给变量 chunk
判断 chunk 是否为真(即是否还有数据)
如果 chunk 是空(b''),循环结束
否则继续循环
💡 := 让你在 一个表达式中完成“读取 + 赋值 + 判断”
2、yield 生成器关键字

yield 是 Python 中**生成器(generator)**的核心关键字。
它的作用:
每次调用函数时,不返回所有结果,而是“逐个产出”结果
函数执行到 yield 时暂停,下次调用再继续
节省内存,适合处理大数据

# ❌ 普通函数:一次性返回所有数据(占内存)
def read_all(file_path):
    with open(file_path, "rb") as f:
        return f.read()  # 整个文件一次性加载进内存

# ✅ 生成器函数:分块返回,边读边处理
def generate_chunks(file_path):
    with open(file_path, "rb") as f:
        while chunk := f.read(1024):
            yield chunk  # 每次只返回一块,不占内存

前缀含义示例用途
b"..."字节字符串(bytes)b"hello"二进制数据、文件、网络传输
f"..."格式化字符串(formatted)f"Hello {name}"字符串插值(类似模板)
r"..."原始字符串(raw)r"C:\new\folder"忽略转义字符(如 \n, \t
10.4、其他类型响应
字符串响应、HTML响应、重定向响应、流式响应
"""
其他返回类型:字符串响应、HTML响应、重定向响应、流式响应
"""
import uvicorn
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from starlette.responses import RedirectResponse
from starlette.staticfiles import StaticFiles

app = FastAPI()

@app.get("/resp1")
async def resp1():
    return "123我就是个普通字符串";

@app.get("/resp2",response_class=HTMLResponse)
async def resp2():
    return "<a href='https://www.baidu.com'>我是一个html,点我跳转到百度</a>";

@app.get("/resp3")
async def resp3():
    """
    重定向到resp2
    """
    return RedirectResponse(url="/resp2")


## 挂载一个静态文件  http://localhost:8000/templates/index.html
app.mount("/templates", StaticFiles(directory="templates",html=True), name="templates")


if __name__ == "__main__":
    uvicorn.run(app="13_response_other:app", host="127.0.0.1", port=8000,reload=True)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值