为什么选择 FastAPI?

  • 高性能:基于 Starlette 和 Uvicorn,支持异步请求处理

  • 开发效率:自动交互文档、类型提示、代码自动补全

  • 现代标准:兼容 OpenAPI 和 JSON Schema

  • 易扩展:模块化设计,支持中间件和依赖注入

以下是一个使用 FastAPI 最新特性 (0.109+) 的完整示例,涵盖核心功能并包含详细注释:

```python
# main.py
from typing import Annotated, Optional
from datetime import datetime, timedelta
from contextlib import asynccontextmanager from fastapi import (
    FastAPI, 
    Depends, 
    HTTPException, 
    status, 
    Query, 
    Body,
    WebSocket,
    Request
)
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
from pydantic import BaseModel, EmailStr, Field
from jose import JWTError, jwt
from passlib.context import CryptContext # ---------------------------
# 应用生命周期与配置
# ---------------------------
@asynccontextmanager
async def lifespan(app: FastAPI):
    """生命周期管理 (FastAPI 2.2+ 新特性)"""
    print("Application startup")
    yield
    print("Application shutdown") app = FastAPI(
    title="Modern FastAPI Demo",
    lifespan=lifespan,
    swagger_ui_parameters={"syntaxHighlight": False}
) # 配置中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
) # 静态文件服务
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates") # ---------------------------
# 安全配置
# ---------------------------
SECRET_KEY = "your-secret-key-keep-it-secret"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30 pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") # ---------------------------
# 数据模型
# ---------------------------
class UserBase(BaseModel):
    username: str = Field(..., example="john_doe")
    email: EmailStr = Field(..., example="john@example.com") class UserCreate(UserBase):
    password: str = Field(..., min_length=8, example="secret123") class UserInDB(UserBase):
    hashed_password: str class Token(BaseModel):
    access_token: str
    token_type: str class TokenData(BaseModel):
    username: Optional[str] = None # ---------------------------
# 工具函数
# ---------------------------
def fake_hash_password(password: str):
    return pwd_context.hash(password) def verify_password(plain_password: str, hashed_password: str):
    return pwd_context.verify(plain_password, hashed_password) def create_access_token(data: dict, expires_delta: timedelta):
    to_encode = data.copy()
    expire = datetime.utcnow() + expires_delta
    to_encode.update({"exp": expire})
    return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) # ---------------------------
# 依赖项
# ---------------------------
async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    # 这里应查询真实数据库
    user = UserInDB(
        username=token_data.username,
        email="user@example.com", 
        hashed_password="fakehashedsecret"
    )
    return user # ---------------------------
# 路由
# ---------------------------
@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
    """返回HTML页面 (集成前端示例)"""
    return templates.TemplateResponse(
        "index.html",
        {"request": request, "message": "Welcome to FastAPI!"}
    ) @app.post("/users/", status_code=status.HTTP_201_CREATED)
async def create_user(user: UserCreate):
    """创建用户 (数据验证示例)"""
    hashed_password = fake_hash_password(user.password)
    return {
        "username": user.username,
        "email": user.email,
        "hashed_password": hashed_password
    } @app.post("/token", response_model=Token)
async def login_for_access_token(
    form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
):
    """OAuth2 认证 (安全示例)"""
    # 验证用户逻辑应替换为真实数据库查询
    user = UserInDB(
        username=form_data.username,
        email="user@example.com",
        hashed_password=fake_hash_password(form_data.password)
    )
    if not verify_password(form_data.password, user.hashed_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, 
        expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"} @app.get("/users/me")
async def read_users_me(
    current_user: Annotated[UserInDB, Depends(get_current_user)]
):
    """需要认证的端点示例"""
    return current_user @app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    """WebSocket 示例"""
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Message received: {data}") @app.get("/items/")
async def read_items(
    q: Annotated[
        Optional[str], 
        Query(
            title="Query string",
            description="Optional search query",
            min_length=3,
            max_length=50
        )
    ] = None,
    page: Annotated[int, Query(ge=1)] = 1,
    size: Annotated[int, Query(ge=1, le=100)] = 10
):
    """复杂查询参数示例"""
    return {"q": q, "page": page, "size": size} @app.post("/compute/")
async def compute_task(
    numbers: Annotated[list[int], Body(embed=True)],
    delay: Annotated[bool, Body()] = False
):
    """后台任务示例"""
    if delay:
        # 模拟长时间任务
        import time
        time.sleep(2)
    
    total = sum(numbers)
    return {"total": total, "count": len(numbers)} # ---------------------------
# 错误处理
# ---------------------------
@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail},
        headers=exc.headers
    ) # ---------------------------
# 运行与测试
# ---------------------------
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "main:app",
        host="0.0.0.0", 
        port=8000,
        reload=True,
        ssl_keyfile="key.pem",  # HTTPS 示例(需生成证书)
        ssl_certfile="cert.pem"
    )
```

### 配套文件结构
```
project/
├── static/
│   └── style.css
├── templates/
│   └── index.html
├── main.py
├── requirements.txt
├── cert.pem
└── key.pem
```

### 主要功能说明

1. **最新生命周期管理**  
使用 `@asynccontextmanager` 管理应用生命周期(FastAPI 2.2+)

2. **安全认证系统**  
- OAuth2 密码流认证
- JWT Token 生成与验证
- 密码哈希加密(使用 passlib)

3. **现代化数据验证**  
- Pydantic V2 模型验证
- 参数注解式声明(Annotated)
- 复杂查询参数约束

4. **高级路由功能**  
- WebSocket 支持
- 静态文件服务
- Jinja2 模板渲染
- 后台任务处理

5. **生产级配置**  
- CORS 中间件
- HTTPS 支持
- 结构化错误处理
- 自动生成文档(Swagger/ReDoc)

6. **类型提示增强**  
- 使用 Python 3.10+ 的类型注解
- 依赖注入系统增强
- 参数元数据声明

### 运行与测试

1. 安装依赖:
```bash
pip install fastapi uvicorn[standard] python-jose[cryptography] passlib jinja2
```

2. 启动服务:
```bash
python main.py
```

3. 访问功能:
- API 文档:`https://localhost:8000/docs`
- WebSocket 测试:`ws://localhost:8000/ws`
- 前端页面:`https://localhost:8000/`

### 测试示例(使用 HTTPie)
```bash
# 创建用户
http POST :8000/users/ username=john email=john@test.com password=secret123

# 获取Token
http POST :8000/token username=john password=secret123

# 访问受保护端点
http GET :8000/users/me "Authorization: Bearer <token>"

# WebSocket测试
websocat ws://localhost:8000/ws
```

这个示例展示了 FastAPI 的现代用法,包含最新的特性实现方式,建议结合官方文档和实际项目需求进行扩展。

python API 之 fastapi的更多相关文章

  1. Appium python API 总结

    Appium python api 根据testerhome的文章,再补充一些文章里面没有提及的API [TOC] [1]find element driver 的方法 注意:这几个方法只能通过sel ...

  2. The novaclient Python API

    The novaclient Python API Usage First create a client instance with your credentials: >>> f ...

  3. Openstack python api 学习文档 api创建虚拟机

    Openstack python api 学习文档 转载请注明http://www.cnblogs.com/juandx/p/4953191.html 因为需要学习使用api接口调用openstack ...

  4. BotVS开发基础—Python API

    代码 import json def main(): # python API列表 https://www.botvs.com/bbs-topic/443 #状态信息 LogStatus(" ...

  5. 《Spark Python API 官方文档中文版》 之 pyspark.sql (一)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  6. 《Spark Python API 官方文档中文版》 之 pyspark.sql (二)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  7. HBase Python API

    HBase Python API HBase通过thrift机制可以实现多语言编程,信息通过端口传递,因此Python是个不错的选择 吐槽 博主在Mac上配置HBase,奈何Zoomkeeper一直报 ...

  8. 二、Blender/Python API总览

    原文:https://docs.blender.org/api/blender_python_api_current/info_overview.html Python in Blender  Ble ...

  9. Appium+python自动化8-Appium Python API

    Appium+python自动化8-AppiumPython API   前言: Appium Python API全集,不知道哪个大神整理的,这里贴出来分享给大家. 1.contexts conte ...

  10. ecCodes 学习 利用ecCodes Python API对GRIB文件进行读写

    参考 https://www.ecmwf.int/assets/elearning/eccodes/eccodes2/story_html5.htmlhttps://confluence.ecmwf. ...

随机推荐

  1. Kotlin:【初始化】主构造函数、在主构造函数里定义属性、次构造函数、默认参数、初始化块、初始化顺序

  2. 关于toString()的小细节

    3. toString()方法3.1 toString()的使用: 1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString() * * 2. Object类中toString()的 ...

  3. Svelte 最新中文文档翻译(1)—— 概述与入门指南

    前言 Svelte,一个非常"有趣".用起来"很爽"的前端框架.从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 ...

  4. LeetCode 力扣 205. 同构字符串

    给定两个字符串 s 和 t ,判断它们是否是同构的. 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的. 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序.不同字 ...

  5. uni-app选中状态并改变颜色

    思路 定义一个数组来记录被点击的元素 arr 数组通过indexOf来来查找 如果有,激活类就是true 没有: 激活类为false 这一步最关键的是查找的内容就是显示出来的index, 点击的时候传 ...

  6. CBAM注意力模型介绍

    本文分享自天翼云开发者社区<CBAM注意力模型介绍>,作者:Liuzijia 近年来,注意力机制在各项深度学习任务中表现出色.研究表明,人类视觉感知过程中,注意力机制发挥了积极的效果,可以 ...

  7. Hetao P1184 宝可梦训练家 [ 绿 ][ 背包dp ][ 线性dp ]

    原题 题解 一道超级牛逼的背包变形,想通之后真的很简单,难点在于想到使用 dp 并且用 dp 的值判断是否合法. 首先观察本题的数据范围:\(1\le n,q \le 10^5\) ,可知本题的询问要 ...

  8. 管理虚拟机(virsh)

    [root@kvm1 qemu]# virsh --help 开启和关闭 [root@kvm1 qemu]# virsh virsh # help list virsh # list virsh # ...

  9. 深度学习:测试是否含有gpu的环境

    在我们跑深度学习的时候,绕不开的一定是gpu显卡,但是如何检测是否使用gpu那?下面我讲提供一段代码,可以检测自己是否开启了gpu或含有gpu. import torch # 检查是否支持 CUDA( ...

  10. 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现

    家里小朋友养了一只小乌龟,到了冬天就冬眠了,早早地准备了一个冬眠箱,铺上椰土,在室温低于15℃时,就把小乌龟放到冬眠箱里,不一会儿它就自己钻入土中把自己藏了起来.按照惯例,需要每隔一定时间,对冬眠箱进 ...