FastAPI入门实战:从零搭建到核心功能详解

文章目录

  • 前言
  • 一、FastAPI是什么
    • [1.1 FastAPI与其他Python Web框架对比](#1.1 FastAPI与其他Python Web框架对比)
    • [1.2 异步与同步的区别](#1.2 异步与同步的区别)
    • [1.3 FastAPI的两大核心组件](#1.3 FastAPI的两大核心组件)
  • 二、如何测试API
    • [2.1 如何测试API](#2.1 如何测试API)
    • [2.2 FastAPI自动生成文档](#2.2 FastAPI自动生成文档)
  • 三、路由
    • 3.1为什么要分包
    • [3.2 路由的基本用法](#3.2 路由的基本用法)
      • [3.2.1 创建路由对象](#3.2.1 创建路由对象)
      • [3.2.2 定义路由和处理函数](#3.2.2 定义路由和处理函数)
      • [3.2.3 应用(包)路由](#3.2.3 应用(包)路由)
  • 四、请求和相应
    • [4.1 路径参数](#4.1 路径参数)
    • [4.2 请求体](#4.2 请求体)
    • [4.3 查询参数](#4.3 查询参数)
    • [4.4 表单提交](#4.4 表单提交)
    • [4.5 文件上传](#4.5 文件上传)
      • [4.5.1 方式一:使用bytes(适合小文件)](#4.5.1 方式一:使用bytes(适合小文件))
      • [4.5.2 方式二:使用UploadFile(适合大文件,推荐)](#4.5.2 方式二:使用UploadFile(适合大文件,推荐))
  • 五、其他请求信息
    • [5.1 Header(请求头)](#5.1 Header(请求头))
    • [5.2 Cookie](#5.2 Cookie)
  • 结语

前言

学习Web开发,选对工具事半功倍。FastAPI以其简洁的设计和强大的性能,正成为Python后端开发的新选择。本文从环境搭建讲起,带你一步步掌握路由设计、参数处理、文件上传等核心技能,助你快速上手现代Web开发。

一、FastAPI是什么

FastAPI是一个用来写网站后端的Python框架。框架就是别人写好的代码库,可以直接拿来用,不用从零开始。

1.1 FastAPI与其他Python Web框架对比

Python有几个主流的Web框架:

  • Django:这是一个"重量级"框架。它什么都已经准备好了,其中数据库、后台管理、用户系统都有。但是问题也在这里------哪怕只是想做一个小功能,也得把整套系统都启动起来。这也是高耦合的一大痛点。
  • Flask:这是一个"轻量级"框架,比Django简单很多,但是需要自己搭配各种组件。
  • FastAPI:也是轻量级的,但设计理念是"高内聚,低耦合"。换句话你来说就是,FastAPI本身只负责核心功能,其他功能可以自由选择第三方库来搭配。这就像乐高积木,需要什么拼什么,很灵活。

相比于Django与Flask来说FastAPI还有一大优势就是支持异步编程。

1.2 异步与同步的区别

可以简单理解的:同步就是一件事做完再做下一件事。异步就是可以同时做几件事,不用等。FastAPI支持异步操作,这样处理请求更快。

1.3 FastAPI的两大核心组件

Starlette :负责网络通信部分。它是一个轻量级的ASGI框架,适合用来搭建高性能的异步服务。
Pydantic:负责数据部分。它主要是进行数据检验操作,利用Python的类型提示功能来检查数据是否符合要求。比如你希望接收一个数字,但用户传了文字,Pydantic会自动报错并给出清晰的错误信息。

二、如何测试API

2.1 如何测试API

写好API后,你需要测试它是否正常工作。我推荐了几个工具:

  • Postman:最经典的API测试功能,功能齐全。
  • Apifox、ApiPost、Yaak:这些都是国内的API测试工具,界面友好,有些还支持中文

注:现在主要用的还是Postman,所以在下面的下面演示中我主要还是用的Postman。

2.2 FastAPI自动生成文档

FastAPI有一个很实用的功能:它会自动给你生成API文档。你不需要额外写文档,访问方式就是先在PyCharm中运行.py文档,再浏览器中输入http://localhost:+你的端口号/docs就能看到Swagger界面。这个界面可以显示所有接口,还能直接在上面测试。

2.2.1 PyCharm中运行.py

再PyCharm中的左下角找到服务(service),再点击添加服务,接着点运行配置,再选择FastAPI即可,你的FastAPI项目名就会显示在这里,再你的FAstAPI项目鼠标右键点击,再点击运行或调试(如果需要的话)即可。




2.2.2 浏览器测试API

默认端口号一般是8000,但是如果不改端口话可能在运行的时候会出现端口占用,运行出错的情况,这是可以修改端口,点击编辑所选配置,按照我下面标出的操作步骤操作。

在再浏览器中输入对应的访问地址即可。

三、路由

3.1为什么要分包

在实际开发中,一个项目通常有很多功能模块,比如用户管理、角色管理、权限管理等。如果把所有的代码文件都堆在项目根目录下,很快就会乱成一团,找文件很费劲。所以,我们需要"分而治之"------把不同功能的代码放到包里,比如:

3.2 路由的基本用法

路由就是URL和处理函数的对应关系。FAstAPI使用APIRouter来创建路由。

3.2.1 创建路由对象

python 复制代码
from fastapi import APIRouter

# 创建一个路由对象
user_router = APIRouter()

3.2.2 定义路由和处理函数

python 复制代码
@user_router.get("/users/{id}")
async def get_user(id: int):
    # {id} 是路径参数,用户访问 /users/123 时,id 就是 123
    print(id)
    return {"id": id, "name": "Alice", "age": 30}

这里的@user_router.get("/users/{id}") 是装饰器,它告诉FAstAPI:当有人用get方法访问/user/{id} 这个地址时,就执行下面的get_user 函数。{id} 是一个变量,可以是任何数字。

3.2.3 应用(包)路由

python 复制代码
from fastapi import FastAPI

app = FastAPI()

# 把user_router注册到app
# prefix="" 表示URL前缀,tags=[] 用于文档分类
app.include_router(user_router, prefix="", tags=["用户"])


@app.get("/")
async def say_hello(name: str):
    return {"message": f"Hello {name}"}

prefix是前缀,比如你想让所有用户相关的地址都以/api开头,就可以写prefix="/api"

四、请求和相应

获取数据的方式有下列5种:

4.1 路径参数

路径参数是URL中的一部分,用花括号{} 表示。比如/user/{id} 中的id 就是路径参数。

python 复制代码
# 路径参数
# Union 联合类型
@user_router.get("/detail/{name}", description="根据用户名查询用户", summary="获取用户信息")
async def get_user_by_name(name: Union[str, None] = None):
    print(name)
    return {"name": name}

其中Union 联合类型是指name这个参数在传参时可以为str或None类型的数据,当然也可以利用Union联合类型给出默认参数,只需要改为name: Union[str, None] = None

4.2 请求体

请求体式客户端发送给服务器的完整数据,通常是post或put请求时携带的JSON数据。FAstAPI用Pydantic模型来定义请求体的结构。

python 复制代码
# 请求体
class User(BaseModel):
    id: int
    name: str = Field(default="张三", max_length=20, min_length=6)
    age: int = Field(default=10, gt=0, lt=150)
    birthday: Union[date, None] = None
    # 简写:
    # birthday: Optional[date] = None
    friends: List[int] = []


# restful 风格的api
@user_router.post("/")
async def add_user(user: User):
    print(user)
    return {"user": user}

在这个示例中应用到了Pydantic来对数据进行验证,这种用法在实际开发中是应用很多的。

在这个代码中Field(default="张三", max_length=20, min_length=6) 意思是默认值(default)是张三,字符串的最大长度(max_length)为20,最小长度(min_length)为6。Field(default=10, gt=0, lt=150) 意思是默认值(default)是10,数据必须要是0~150之间的数值。friends: List[int] = [] 是定义了一个列表,要传入的参数要是int类型的数据。

4.3 查询参数

查询参数跟在URL的问号后面,比如 /users?name=Tom&age=20

特别提醒:路径后面一定要加斜杠 /

python 复制代码
@user_router.get("/info/")
async def get_user_info(name: str, age: int):
    # name 和 age 是查询参数
    # 用户访问 /info/?name=Tom&age=20 时,这两个参数会自动解析
    print(name)
    print(age)
    return {"name": name, "age": age}

注意:如果不加斜杠写成 /info,访问 /info?name=Tom 时可能会出问题。

4.4 表单提交

要处理表单数据,需要先安装一个库:

shell 复制代码
pip install python-multipart

安装好之后就可以处理提交的表单数据了。

python 复制代码
@user_router.post("/login/")
async def login(name: str = Form(...), password: str = Form(...)):
    print(name)
    print(password)
    return {"name": name, "password": password}

4.5 文件上传

文件上传有两种方式:bytesUploadFile

4.5.1 方式一:使用bytes(适合小文件)

python 复制代码
# 文件上传
@user_router.post("/upload/")
async def upload(file: bytes = File(...)):
    """
    单文件上传
    :param file:
    :return:
    """
    print(f"文件上传成功,大小为:{len(file)}")
    return {"file_size": len(file)}


@user_router.post("/uploads/")
async def upload_multiple_files(files: List[bytes] = File(...)):
    """
    多文件上传
    :param file:
    :return:
    """
    for file in files:
        print(f"文件上传成功,大小为:{len(file)}")
    return {
        "size": [len(file) for file in files]
    }

4.5.2 方式二:使用UploadFile(适合大文件,推荐)

对于大文件,用 bytes 会导致内存占用过高。UploadFile 提供了更友好的接口,它不会一次性把文件读入内存。

python 复制代码
@user_router.post("/file/upload/")
async def file_upload(file: UploadFile):
    """
    单文件上传
    :param file:
    :return:
    """
    if file:
        print(file.filename, file.content_type)

        # 上传文件
        with open(file.filename, "wb") as f:
            f.write(await file.file.read())
    return {"filename": file.filename, "content_type": file.content_type}


@user_router.post("/file/uploads/")
async def file_uploads(files: List[UploadFile] = File(...)):
    """
    UploadFile实现多文件上传
    :param files:
    :return:
    """
    for file in files:
        print(file.filename, file.content_type)
        # 上传文件
        with open(file.filename, "wb") as f:
            f.write(await file.file.read())
    return {"filename": [file.filename for file in files], "content_type": [file.content_type for file in files]}

五、其他请求信息

5.1 Header(请求头)

请求头包含了很多元信息,比如用户的浏览器类型、认证令牌等。

Cookie是服务器保存在用户浏览器里的小段数据。它常用于识别用户身份,比如"记住登录状态"。当用户再次访问时,浏览器会自动带上Cookie,服务器就能认出这个用户。

python 复制代码
@user_router.get("/request/")
async def get_request(request: Request):
    # 获取请求头 headers Mapping(K-V)
    content_type = request.headers.get("Content-Type")
    print(content_type)

    print("-" * 20)

    # 获取 cookie 字典
    print(request.cookies)

    # URL对象,有很多属性  hostname(主机) path(路径) port(端口)
    print(request.url.path)
    print(request.url.port)
    print(request.url.hostname)

    # 获取到请求方式(get/post)
    print(request.method)

在上述所有的代码中能用到的模块,包括:

python 复制代码
from datetime import date
from typing import Union, List

from fastapi import APIRouter, Form, File, Request, UploadFile
from pydantic import BaseModel, Field

注:不要从库中导错模块了。

结语

掌握FastAPI只是开始。异步编程的思维、模块化的设计理念,这些能力会伴随你的整个编程生涯。希望本文能成为你技术路上的一块垫脚石,助你写出更优雅、更高效的代码。

相关推荐
曲幽10 小时前
FastAPI + Vue 前后端分离实战:我的项目结构“避坑指南”
python·vue·fastapi·web·vite·proxy·cors·env
DYuW5gBmH20 小时前
FastAPI 实战:WebSocket 从入门到上线,使用避坑指南
websocket·网络协议·fastapi
MwEUwQ3Gx1 天前
FastAPI + SQLAlchemy 2.0 + Alembic 从零搭建,踩坑实录
fastapi
eF06U766F1 天前
Nacos 和 Apollo,哪个更好?
fastapi
别抢我的锅包肉1 天前
【FastAPI】 + SQLAlchemy 异步 ORM 实现完整 CRUD 操作
前端·fastapi
MasonYyp1 天前
使用FastAPI和StreamableHTTP实现打字机流式对话
fastapi
oG99bh7CK1 天前
FastAPI + PostgreSQL 实战:从入门到不踩坑,一次讲透
数据库·postgresql·fastapi
IeE1QQ3GT1 天前
FastAPI + SQLite:从基础CRUD到安全并发的实战指南
安全·sqlite·fastapi
taWSw5OjU1 天前
FastAPI + PostgreSQL 实战:给应用装上“缓存”和“日志”翅膀
缓存·postgresql·fastapi