FastAPI快速入门

欢迎来到啾啾的博客🐱。
记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。
有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。

引言

本篇是一个Java程序员的FastAPI快速入门。

资料:https://fastapi.tiangolo.com/tutorial/bigger-applications/

1 服务器Uvicorn

Python的FastApi默认使用的内嵌服务器是Uvicorn,支持并发,线程管理交于外部组件。

Uvicorn是纯异步I/O,适合Python生态的异步架构,。
不同于Tomcat的NIO与半阻塞的线程管理,也不同于Netty通过Reactor模式实现全链路非阻塞的多路复用。

特性UvicornTomcat NIONetty
网络模型异步 I/O(Asynchronous)多路复用 NIO(Non-blocking)多路复用(Reactor 模式)
I/O 处理方式全程非阻塞(事件循环 + 协程)连接监听非阻塞,请求处理阻塞全程非阻塞(EventLoop 线程)
线程模型单线程事件循环 + 协程池Acceptor/Poller + 阻塞线程池主从线程组(Boss/Worker)
协议支持HTTP/1.1、WebSocket、HTTP/2HTTP/1.1、HTTP/2(有限)自定义协议(HTTP/WebSocket等)
适用场景高并发 API、实时通信传统 Web 应用、Servlet 容器高性能网络中间件、实时系统

2 接口

使用装饰器声明接口,比如:@app.get()@app.post()

3 Pydantic

FastAPI基于Pydantic来构建SpringBoot中常见的model,如xxRequest。但Pydantic模型功能更多,相当于集校验@Valid、文档@API等于一身。

FastAPI 是基于 Starlette (Web 部分) 和 Pydantic (数据验证部分) 构建的。
其中,Pydantic 是一款用于 Python 数据验证和设置管理 的库。

简单来说,它的核心作用就是:

  • 把普通的数据(比如字典、JSON)变成结构化的数据对象。
  • 在转换过程中,严格检查数据是否符合你定义的规则。

Pydantic的核心是BaseModel。通过继承它来定义自己的数据模型,这个模型就是告诉Pydantic开发者期望的数据结构。

from pydantic import BaseModel, EmailStr
from typing import Optional

class User(BaseModel):
    name: str
    age: int
    email: Optional[EmailStr] = None

上面这个 User 类就定义了一个模型:

  • 它必须有 name 字段,且类型是 str
  • 它必须有 age 字段,且类型是 int
  • 它有一个可选的 email 字段,类型是 EmailStr(Pydantic 内置的邮箱验证类型),默认值为 None

Pydantic会自动校验模型内容:

data = {
  "name": "张三",
  "age": "25", # 注意这里 age 是字符串
  "email": "zhangsan@example.com"
}

try:
    user = User(**data)
    print(user.name)  # 输出: 张三
    print(user.age)   # 输出: 25 (Pydantic 自动转换为整数)
    print(user.email) # 输出: zhangsan@example.com
    print(user)       # 输出: name='张三' age=25 email='zhangsan@example.com'
except Exception as e:
    print(e)

在这个例子中,Pydantic 做了以下几件事:

  • 它检查了所有字段。
  • 它发现 age 是字符串 "25",但模型要求是 int,于是它 自动完成了类型转换
  • 它甚至检查了 email 的格式,确保它是一个有效的邮箱地址。

另外,在FastAPI中,当请求体不符合Pydantic模型时,FastAPI会自动返回 422 Unprocessable Entity 错误响应,而无需手动 try...except

4 FastAPI的“依赖注入”

FastAPI的依赖注入允许声明你的路由操作(也就是那些用 @app.get()、@app.post() 等装饰器定义的函数)或者其他依赖所需要的“组件”或“服务”。FastAPI 会自动帮你把这些依赖“注入”到你的函数中。

FastAPI 的依赖注入系统基于可调用对象(函数或类)。你定义一个函数,让它返回你需要的依赖对象。然后,在你的路径操作函数中,使用 fastapi.Depends() 来声明你需要这个依赖。

比如认证依赖:

from fastapi import FastAPI, Depends, HTTPException, status
from typing import Annotated # Python 3.9+ 推荐使用 Annotated

app = FastAPI()

# 这是一个模拟的用户数据库
fake_users_db = {
    "john_doe": {
        "username": "john_doe",
        "email": "john@example.com",
        "hashed_password": "fakehashedpassword" # 实际应用中会是加密后的密码
    }
}

# --- 定义一个简单的认证依赖 ---
# 这个函数会从请求头中获取一个 token,并验证它
async def get_current_user_from_token(token: str):
    # 假设你的 token 就是用户名,这里只是一个简化示例
    # 实际应用中,你会验证 JWT、API Key 或者其他认证凭证
    if token not in fake_users_db:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效的认证凭据",
            headers={"WWW-Authenticate": "Bearer"}, # 告诉客户端需要 Bearer Token
        )
    user_data = fake_users_db[token]
    return user_data

# --- 定义另一个更高级的依赖:获取当前活跃用户 ---
# 这个依赖依赖于上面的 get_current_user_from_token
async def get_current_active_user(
    current_user: Annotated[dict, Depends(get_current_user_from_token)] # 这里使用了 Depends 来依赖上一个函数
):
    # 假设我们有一个用户状态,比如 is_active
    if not current_user.get("is_active", True): # 默认用户是活跃的
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="非活跃用户")
    return current_user

# --- 路由:需要认证才能访问的用户信息 ---
@app.get("/users/me/")
async def read_users_me(
    current_user: Annotated[dict, Depends(get_current_active_user)] # 在这里注入依赖
):
    """
    获取当前登录用户的信息。
    需要提供有效的认证令牌。
    """
    return {"message": "欢迎回来!", "user": current_user}

# --- 路由:一个不需要认证的公开接口 ---
@app.get("/")
async def read_root():
    """
    这是一个公开接口,不需要任何认证。
    """
    return {"message": "Hello, World!"}

# 如何运行:
# 1. 保存代码为 main.py
# 2. 在命令行运行:uvicorn main:app --reload
# 3. 访问:
#    - http://127.0.0.1:8000/
#    - http://127.0.0.1:8000/users/me/ (不带token会401)
#    - 带token访问:使用 Postman 或 curl,在请求头中添加 "token": "john_doe"
#      curl -X 'GET' 'http://127.0.0.1:8000/users/me/' -H 'accept: application/json' -H 'token: john_doe'

在这个例子中,Depends的使用接近于Spring AOP的Before的编织效果。
依赖注入不仅限于认证,还可以注入数据库连接、配置对象、工具函数等任何你需要在路径操作中使用的“服务”。

5 依赖管理

pip与requirements.txt可以实现简单的依赖管理,其快捷、方便。

pip freeze > requirements.txt

但是对于复杂项目来说,存在不能辨别冲突依赖、区分依赖组、精确锁定依赖的问题。

可以使用Poetry或者PDM进行统一的依赖管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tataCrayon|啾啾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值