FastAPI API开发指南 | 豆包MarsCode AI刷题

115 阅读11分钟

基础

引言与快速入门

欢迎来到我的FastAPI奇妙之旅!Wanna learn how to build awesome APIs with me? 快来跟着我一起看看为什么选择FastAPI吧!它可是Python3.7+的明星框架呢!想快速开发高效的RESTful API吗?那当然要选用FastAPI啦!它简直是天生为API量身定制的,自动生成文档、类型注解支持,性能也是杠杠的!

比方说,如果你的代码运行速度慢,或者你写代码的时候总是担心出错的话,那选择FastAPI绝对不会让你失望哦~ 它会像一位贴心的老师一样,帮你提高效率,写出更稳健的代码。

准备好开始了吗?你需要Python3.7或更高版本,先去看看你的版本是多少吧!

python --version

如果版本过低,记得从官网下载最新的版本哦~接下来,咱们需要安装一些好东西:FastAPI和Uvicorn。别担心,这很容易!

  1. 安装 FastAPI: 在终端中输入

    pip install fastapi
    
  2. 安装 Uvicorn: 为了让我们的应用起来运行,我们需要一个叫Uvicorn的服务器来帮忙哦~ 运行:

    pip install uvicorn
    

现在我们已经准备就绪啦!是不是很激动呢?别急,接下来的内容会带你逐步了解FastAPI!

构建RESTful API接口

看这个,我们来搭建一个RESTful API接口吧!是不是很刺激?!

首先,我们要想好我们的API要做什么。比如,你想做一个用户管理系统吗?可以获取所有用户信息,还能添加新用户呢!想想就激动人!

那我们就要设计一下资源路径和请求方法咯!GET请求用来获取信息,POST请求用来添加新的信息。听起来是不是很像玩游戏呀?你知道GET 和POST的区别吗?嘻嘻嘻?

现在我给你展示一下代码片段,实现一个用户管理系统:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    id: int
    name: str
    email: str

users_db = {
    1: User(id=1, name="John Doe", email="john@example.com"),
    2: User(id=2, name="Jane Doe", email="jane@example.com")
}

@app.get("/users/")
async def read_users():
    return users_db.values()

@app.post("/users/")
async def create_user(user: User):
    new_id = max(users_db.keys()) + 1
    user.id = new_id
    users_db[new_id] = user
    return {"message": "User created successfully", "user": user}

这个代码片段定义了两个路由:GET /users/ 用于获取所有用户信息,POST /users/ 接收一个 User 对象作为请求体,创建一个新的用户并返回创建的结果。真棒吧!

现在运行你的FastAPI应用,访问 http://127.0.0.1:8000/docs 可以看到自动生成的文档哦!是不是很酷炫?

你还在等什么呢?快来体验一下吧!

深入

数据库集成与数据验证

想知道怎么用SQLAlchemy连接数据库来玩儿数据吗?那就跟着我来吧!

首先,你需要把FastAPI、Uvicorn 和 SQLAlchemy 这些好朋友都邀请到你的项目里去,就像这样:

pip install fastapi uvicorn sqlalchemy alembic

然后呢,咱们就创建一个新的Python文件,比如“main.py”,导入需要的库啦~

接下来我们要定义一个ORM模型,就像画图一样,用代码描述数据库表的样子。比如说你想有一个用户表,那咱们就先定义一下用户的形状:

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class User(Base):
    __tablename__ = "users"  # 告诉它这是个用户表,数据库里会这样命名
    id = Column(Integer, primary_key=True, index=True)  # 主键,每个用户的ID都是独一无二的
    username = Column(String, unique=True, index=True)  # 用户名要唯一哦!
    email = Column(String, unique=True, index=True)     # 邮箱也要唯一才行~

看吧,是不是很简单?ORM模型就像给数据库画了一张图纸,告诉它每个字段是什么样子的。接下来呢,咱们就可以用这个“User”模型来操作数据库啦!

嘿嘿嘿~ 咱来聊聊数据库吧!连接数据库可简单了,就像给你的代码找个好朋友一样,方便它去捞取数据啦~

你看这个例子:

from sqlalchemy.orm import Session
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base

DATABASE_URL = "sqlite:///./test.db"  # 咱用SQLite当例子,想换成别的数据库?随意啊!
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base.metadata.create_all(bind=engine)

瞧,咱用 create_engine() 生成了个引擎,就像一把钥匙一样打开数据库的大门。sessionmaker() 则是帮我们创建了一个会话工厂,保证每一次访问数据库都安全可靠地结束。

然后呢? 数据验证就变得像游戏里升级似的!要确保你的数据是干净的,不能有任何小错误啦~ 比如:

from fastapi import HTTPException, status

def validate_user_data(username: str, email: str):
    if not username or not email:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Username and Email are required")
    
    # 想加点什么验证? 随便你!

你看这个 validate_user_data 函数,就像个守护神一样,确保你的数据是完整的和安全的。

怎么样?不觉得这些都是很酷的功能吗?

用户认证机制

用户认证? 哼哼,这可是我玩儿得最溜的事儿!想让你的 API 变得更安全点儿?我来给你说一说 fastapi-users 这个库吧!你先把这个库给安装上:

pip install fastapi-users[sqlalchemy]

然后,创建一个文件,比如叫 auth.py,里面设置认证系统,看这个样子:

from fastapi_users import FastAPIUsers
from fastapi_users.authentication import JWTStrategy, AuthenticationBackend

SECRET = "your-secret-key"  # 这玩意儿要你自己设定哦!

# 需要替换为你的用户表定义
from your_project.models import User 

def get_jwt_strategy() -> JWTStrategy:
    return JWTStrategy(secret=SECRET, lifetime_seconds=3600)

auth_backend = AuthenticationBackend(
    name="jwt",
    verify_token=get_jwt_strategy,
    token_url="/auth/jwt/login"
)

fastapi_users = FastAPIUsers[User, int](get_user_manager, [auth_backend], User.get_id)
current_user = fastapi_users.current_user()

这样,你就搭建好了基本的用户认证系统,可以通过 /auth/jwt/login 路径登录并获取 JWT Token。

进阶

异常处理与日志记录

异常处理和日志记录?这可是我的强项呢!你想让你的 API 变得更健壮,更易于维护吗?那就来听我娓娓道来吧!

首先,我们要给那些“oops”时刻做好准备,比如数据库连接失败、请求参数不合法等等。我们可以用自定义异常类来优雅地处理这些错误,就像这样:

from fastapi import HTTPException, status

class ItemNotFound(HTTPException):
    def __init__(self):
        super().__init__(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Item not found",
            headers={"X-Error": "There goes my error"}
        )

你看,我们定义了一个 ItemNotFound 异常类,专门用来处理找不到物品的情况。这样一来,当你的 API 在找不到指定物品的时候,就不会直接崩溃啦!还附带了超详细的错误信息呢!真是太贴心了吧?

然后,在处理请求的函数中,我们可以像这样使用这个自定义异常:

from fastapi import Depends, HTTPException

def get_item(id: int):
    if id > 10:
        raise ItemNotFound()
    return {"id": id, "name": f"Item {id}"}

看,是不是很简洁?当 id 超过 10 时,就会抛出 ItemNotFound 异常。这样你的 API 就变得更加稳健啦!

至于日志记录,FastAPI 内置了一个简单实用的机制,可以记录请求和响应信息。你可以在你的主文件或其他相关文件中启用它:

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    await log_request_response()  # 这句代码就负责记录日志啦!
    return {"message": "This is a response"}

这样,每次请求你的 API 时,就会自动记录下相关信息。你也可以使用第三方库来调整日志级别和格式,让日志更加详细、更有用。

是不是觉得我超棒的?

安全性考量、性能优化与部署准备

呀,安全性、性能优化和部署准备?这些可是打造一个“顶尖” API 的关键步骤呢!你想让你的 API 既安全又高效,那可得好好听我讲解了!

首先,咱要想想那些 pesky little bugs,比如 SQL 注入和 XSS 攻击。要防止它们入侵我们的应用程序,咱们就得做好防护措施!别看代码写得多干净,如果没有防范措施,就很容易被这些坏蛋钻漏洞哦!你想让你的 API 像一座金玉满堂的城堡一样安全可 靠吗?

  • SQL注入: 在使用 SQL 查询语句的时候,一定要注意不要直接将用户输入当作查询条件。这就好比打开你的大门,任由陌生人随意进来一样危险!我们可以通过使用 ORM 模型或参数化查询来进行数据库操作,就像是在城堡门前设置一道安全的栅栏一 样,确保只有经过授权的人才能进入哦!

    from fastapi import APIRouter, Depends
    from sqlalchemy.orm import Session
    from .database import get_db
    from .models import Item
    
    router = APIRouter()
    
    @router.get("/items/")
    def read_items(db: Session = Depends(get_db)):
        items = db.query(Item).all()
        return items
    

这样,你就可以确保数据库操作的安全性了。

  • XSS攻击: 为了防止 XSS,咱们要对用户输入进行转义处理,就像给它们穿上盔甲一样!这意味着将 HTML 标签转换为安全的格式,防止它们被恶意利用。你可以使用前端库来帮助你处理这些内容,比如 html 库就是这样一款神器!

接下来是 HTTPS 和 CORS 的配置,这两项也是保障 API 安全性的重要组成部分:

  • HTTPS协议: 要使用 HTTPS 协议,你需要获取证书。你可以使用 Let's Encrypt 等服务来获得免费的 SSL 证书,然后将它们安装到你的 Web 服务器上。就像为你的城堡穿上了一层保护膜一样!

  • CORS(跨域资源共享): CORS 用于控制不同域名的网页访问权限。你可以使用 FastAPI 的 CORSMiddleware 来配置 CORS 设置,允许特定的域名访问你的 API。就像在你的城堡门口设置了门卫,只允许特定的人进来一样!看看这个例子吧:

    from fastapi.middleware.cors import CORSMiddleware
    
    app = FastAPI()
    
    origins = ["http://localhost:3000"]
    
    app.add_middleware(
        CORSMiddleware,
        allow_origins=origins,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    

哎呀,性能优化?哼哼,这可真是个考验实力的好题呢!如果你想让你的 API 像闪电一样快,那你就得好好听我讲解了!

首先,咱们要想想异步编程,就像一个多手选手一样,可以同时处理多个请求,而不是像傻瓜一样排队等待!我们可以使用 asyncio 这个厉害的库来实现异步编程,就像给你的 API 加上了加速器一样!比如这段代码用 asyncawait 就实现了异步 操作,是不是很酷炫?

import asyncio

async def slow_operation():
    await asyncio.sleep(1)
    return {"message": "Hello, world!"}

@app.get("/slow/")
async def read_slow_item():
    result = await slow_operation()
    return result
import asyncio

app = FastAPI()

@router.get("/items/{item_id}")
async def read_item(item_id: int, cache=Depends(cache_dependency)):
    # 使用异步方法获取数据...
    item = await get_from_redis(cache, f"item:{item_id}")
    if not item:
        # 如果没有缓存,就从数据库取数据
        item = await db_get_item(item_id)
        await set_in_redis(cache, f"item:{item_id}", item)
    return {"message": "This is a response", "data": item}

然后呢,Redis 缓存就好像是一个超级快的仓库,我们可以把经常被访问的数据存放在这里,这样的话每次访问的时候就不需要从数据库那里取了,就像在家里备好零食一样方便!那不妨看看如何使用 Redis 来实现缓存吧:

import asyncio

# 假设 `cache_dependency` 是一个依赖项函数,用于获取缓存实例
async def get_from_redis(cache, key):
    # 从 Redis 获取数据的异步方法
    return await cache.get(key)

async def set_in_redis(cache, key, value):
    # 将数据写入 Redis 的异步方法
    await cache.set(key, value)

看这个 Docker 容器化部署和 Gunicorn 服务器配置部分,简直太方便了啦!你想把你的 API 部署起来,可是又懒得折腾?那你就必须看看我给你的这份宝藏指南!

首先呢,我们来写一个 Dockerfile 文件,就像为你的应用准备了一个豪华的家一样!这个文件里边告诉 Docker 使用哪个 Python 版本、把你的代码搬到容器里,还有安装需要的工具等等。比如这个:

# 使用官方的 Python 运行时作为父镜像
FROM python:3.9-slim

# 设置容器的工作目录
WORKDIR /app

# 将本地文件复制到容器中的 /app 目录
COPY . /app

# 安装所需的依赖包
RUN pip install --no-cache-dir -r requirements.txt

# 暴露 80 端口以便外部访问
EXPOSE 80

# 设置环境变量
ENV NAME World

# 启动应用时运行 uvicorn
CMD ["uvicorn", "main:app", "--reload"]

然后呢,我们再写一个 docker-compose.yml 文件,它就像一个指挥家一样,管理着你的整个应用环境。你看这里边配置了 Gunicorn 服务器和数据库等等,把它们串联起来,这样你的应用就能像一辆跑得快、稳健的机器一样运转!

version: '3.1'

services:
  web:
    build: .
    ports:
      - "8000:80"
    volumes:
      - .:/app
    depends_on:
      - db

  db:
    image: postgres:latest

最后,运行 docker-compose up --build 这个命令,就像启动你的应用的魔法一样!Boom!你的 API 就正式上线啦!