为什么选择 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. 第五章 非对称加密算法--DH--RSA

    13.1.DH 非对称算法的基石 仅能用于密钥分配,不能用于加解密数据,一般加密数据用AES 密钥长度:512~1024中的64的整数倍 双方各有自己的密钥对 13.2.RSA 最经典的非对称加密算法 ...

  2. C# webapi 允许跨域(.NET Framework)

    实际项目中,对于WebApi的访问不一定都在同一域名下,所以进行跨域访问的时候,可能会出现如下提示:请求的资源不支持 http 方法"OPTIONS".需要对WebApi进行设置. ...

  3. 使用badboy配合jmeter测试(详细)

    工具 badboy2.2.5  jmeter 5.4.1 两个工具都必须是最新版,否则jmeter打开脚本的时候会报错 1.首先打开badboy,首页如下图 2.进入后就开始自动录制脚本,可以输入要测 ...

  4. 面试题: == 和 equals() 区别【包装类重写了object类中的equals方法】

    /* * * 面试题: == 和 equals() 区别 * * 一.回顾 == 的使用: * == :运算符 * 1. 可以使用在基本数据类型变量和引用数据类型变量中 * 2. 如果比较的是基本数据 ...

  5. atomikos实现分布式事务

    date: 2022-04-25 categories: [java, 编程] tags: [分布式事务] 概述 多数据源单服务写入, 分布式事务实现 使用随机数控制产生异常 注: 网上很多都是只有多 ...

  6. JS深度理解

    事件循环 程序运行需要有自己专属的内存空间,可以把这块内存简单理解为进程 每个应用至少有一个进程,进程间相互独立,要通信,也需要双方同意 线程 有进程后,就可以运行程序的代码 运行代码的 [人] 称为 ...

  7. 第11章 其他 XML 技术

    第11章 其他 XML 技术 概述 System.Xml 命名空间由以下命名空间和核心类型构成: ​System.Xml.*​ ​XmlReader​ 和 XmlWriter​:高性能.前向读写的 X ...

  8. HTML布局常用标签——div和span

    HTML布局常用标签--div和span 在HTML的世界里,div和span是两位不可或缺的老朋友,它们虽然看似简单,却在网页布局和样式设计中发挥着举足轻重的作用.今天,我们就来聊聊这两位" ...

  9. Ansible之一module

    常用自动化运维工具 Ansible:python,Agentless,中小型应用环境 saltstack:python,一般需部署agent,执行效率更高 puppet:ruby,功能强大,配置复杂, ...

  10. 手把手教你在个人电脑部署本地知识库(基于RAGFlow + DeepSeek [+ Ollama])

    1.    实现方案及准备工作 按照教程一步一步操作,基本没有什么太大难度,稍显麻烦的可能就是因网络问题有些资源无法下载,对于镜像无法下载的问题,文中也提供了替代的方法,但是github访问不稳定这点 ...