在现代应用开发中,快速构建数据库驱动的API服务是常见需求。FastAPI作为高性能Python框架,结合SQLite这一轻量级嵌入式数据库,能帮助我们快速实现简单但实用的后端服务。本文将通过一个完整的“学生信息管理”示例,手把手带你从0到1搭建一个数据库API服务。
一、环境准备:安装必要工具¶
首先,我们需要安装FastAPI、SQLite的Python接口(SQLAlchemy,用于ORM操作)和服务器(Uvicorn)。打开终端,执行以下命令:
pip install fastapi uvicorn sqlalchemy
- FastAPI:Python高性能Web框架,自动生成API文档,支持异步操作。
- Uvicorn:ASGI服务器,用于运行FastAPI应用。
- SQLAlchemy:ORM(对象关系映射)库,让Python代码可直接操作数据库,无需写原生SQL。
- SQLite:无需独立服务器的嵌入式数据库,适合开发和小型项目。
二、核心概念:数据模型与数据库连接¶
我们以“学生信息”为例,先定义数据模型和数据库连接。创建一个main.py文件,按以下步骤编写代码:
1. 导入依赖¶
from fastapi import FastAPI, HTTPException, Depends
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
from pydantic import BaseModel
2. 定义数据模型¶
使用SQLAlchemy定义数据库表结构(ORM模型),这里我们创建一个Student模型,对应数据库中的students表:
# 1. 连接SQLite数据库(文件存储,无需额外服务器)
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db" # 数据库文件路径为当前目录下的test.db
# 2. 创建SQLAlchemy引擎(核心连接对象)
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} # SQLite专用参数
)
# 3. 创建会话本地类(用于操作数据库)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# 4. 定义基类(所有ORM模型继承自它)
Base = declarative_base()
# 5. 定义Student模型(对应数据库表)
class Student(Base):
__tablename__ = "students" # 表名
id = Column(Integer, primary_key=True, index=True) # 主键,自增
name = Column(String, index=True, nullable=False) # 学生姓名(非空)
age = Column(Integer, nullable=True) # 学生年龄(可选)
3. 创建数据库表¶
在第一次运行时,需要创建表结构。可以通过SQLAlchemy的create_all()方法自动生成表:
# 创建所有表(需在定义完模型后执行)
Base.metadata.create_all(bind=engine)
4. 定义Pydantic模型(数据验证与序列化)¶
FastAPI需要明确请求/响应的数据格式,我们用Pydantic定义数据模型:
# 用于请求数据的模型(无需id,由数据库自动生成)
class StudentCreate(BaseModel):
name: str
age: int | None = None # 年龄可选
# 用于响应数据的模型(包含id)
class StudentResponse(BaseModel):
id: int
name: str
age: int | None = None
class Config:
orm_mode = True # 允许从ORM对象(SQLAlchemy模型)中读取数据
三、数据库操作函数(CRUD)¶
接下来,编写操作数据库的函数(CRUD:创建、读取、更新、删除)。我们通过SQLAlchemy的会话(Session)执行数据库操作:
# 依赖项:获取数据库会话(每次请求生成新会话,用完关闭)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# 1. 创建学生(POST /students)
def create_student(db: Session, student: StudentCreate):
db_student = Student(name=student.name, age=student.age)
db.add(db_student)
db.commit()
db.refresh(db_student) # 刷新数据,获取数据库生成的id
return db_student
# 2. 获取单个学生(GET /students/{student_id})
def get_student(db: Session, student_id: int):
return db.query(Student).filter(Student.id == student_id).first()
# 3. 获取所有学生(GET /students)
def get_all_students(db: Session, skip: int = 0, limit: int = 100):
return db.query(Student).offset(skip).limit(limit).all()
# 4. 更新学生(PUT /students/{student_id})
def update_student(db: Session, student_id: int, student_update: StudentCreate):
db_student = get_student(db, student_id)
if not db_student:
return None
# 更新字段(仅name和age,id不可修改)
db_student.name = student_update.name
db_student.age = student_update.age
db.commit()
db.refresh(db_student)
return db_student
# 5. 删除学生(DELETE /students/{student_id})
def delete_student(db: Session, student_id: int):
db_student = get_student(db, student_id)
if not db_student:
return False
db.delete(db_student)
db.commit()
return True
四、搭建FastAPI路由(API端点)¶
现在,将CRUD函数与FastAPI路由绑定,实现具体的API接口:
# 创建FastAPI实例
app = FastAPI(title="学生信息管理API")
# 1. 创建学生(POST请求)
@app.post("/students", response_model=StudentResponse, status_code=201)
def create_student_endpoint(student: StudentCreate, db: Session = Depends(get_db)):
db_student = create_student(db=db, student=student)
return db_student
# 2. 获取单个学生(GET请求)
@app.get("/students/{student_id}", response_model=StudentResponse)
def get_student_endpoint(student_id: int, db: Session = Depends(get_db)):
db_student = get_student(db, student_id)
if not db_student:
raise HTTPException(status_code=404, detail="学生不存在")
return db_student
# 3. 获取所有学生(GET请求)
@app.get("/students", response_model=list[StudentResponse])
def get_all_students_endpoint(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
students = get_all_students(db, skip=skip, limit=limit)
return students
# 4. 更新学生(PUT请求)
@app.put("/students/{student_id}", response_model=StudentResponse)
def update_student_endpoint(student_id: int, student: StudentCreate, db: Session = Depends(get_db)):
db_student = update_student(db, student_id, student)
if not db_student:
raise HTTPException(status_code=404, detail="学生不存在")
return db_student
# 5. 删除学生(DELETE请求)
@app.delete("/students/{student_id}", status_code=204)
def delete_student_endpoint(student_id: int, db: Session = Depends(get_db)):
success = delete_student(db, student_id)
if not success:
raise HTTPException(status_code=404, detail="学生不存在")
return None
五、运行与测试API服务¶
1. 启动应用¶
在终端执行以下命令启动服务(--reload开启热重载,修改代码后自动重启):
uvicorn main:app --reload
main:文件名(main.py)app:FastAPI实例名- 启动后,访问
http://127.0.0.1:8000/docs或http://127.0.0.1:8000/redoc可查看交互式API文档。
2. 测试API¶
使用FastAPI的交互式文档(Swagger UI)或命令行工具测试:
-
创建学生:
点击/docs中的POST /students→ 点击“Try it out” → 输入JSON数据(如{"name": "Alice", "age": 20})→ 点击“Execute”。 -
获取单个学生:
点击GET /students/{student_id}→ 输入刚创建的学生ID(如1)→ 点击“Execute”。 -
其他操作:
同理测试GET /students(获取所有)、PUT /students/{id}(更新)、DELETE /students/{id}(删除)。
六、总结¶
通过本文,你已完成一个基于FastAPI+SQLite的轻量级数据库API服务。核心优势包括:
- 轻量易用:SQLite无需额外服务器,FastAPI自动生成API文档,降低开发门槛。
- 高性能:FastAPI支持异步操作,适合高并发场景(但SQLite本身是单线程,适合中小规模)。
- 扩展性强:可通过修改SQLAlchemy模型和路由,快速支持复杂业务(如多表关联、权限控制)。
后续可尝试扩展:添加分页、过滤、排序功能,或迁移到PostgreSQL/MySQL等数据库。
完整代码示例(可直接复制到main.py运行):
from fastapi import FastAPI, HTTPException, Depends
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
from pydantic import BaseModel
# 数据库配置
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# 学生模型(数据库表)
class Student(Base):
__tablename__ = "students"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True, nullable=False)
age = Column(Integer, nullable=True)
Base.metadata.create_all(bind=engine) # 创建表
# Pydantic模型(数据验证)
class StudentCreate(BaseModel):
name: str
age: int | None = None
class StudentResponse(BaseModel):
id: int
name: str
age: int | None = None
class Config:
orm_mode = True
# 数据库会话依赖
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# 数据库操作函数
def create_student(db: Session, student: StudentCreate):
db_student = Student(name=student.name, age=student.age)
db.add(db_student)
db.commit()
db.refresh(db_student)
return db_student
def get_student(db: Session, student_id: int):
return db.query(Student).filter(Student.id == student_id).first()
def get_all_students(db: Session, skip: int = 0, limit: int = 100):
return db.query(Student).offset(skip).limit(limit).all()
def update_student(db: Session, student_id: int, student: StudentCreate):
db_student = get_student(db, student_id)
if not db_student:
return None
db_student.name = student.name
db_student.age = student.age
db.commit()
db.refresh(db_student)
return db_student
def delete_student(db: Session, student_id: int):
db_student = get_student(db, student_id)
if not db_student:
return False
db.delete(db_student)
db.commit()
return True
# FastAPI应用
app = FastAPI(title="学生信息API")
# API路由
@app.post("/students", response_model=StudentResponse, status_code=201)
def create_student_endpoint(student: StudentCreate, db: Session = Depends(get_db)):
return create_student(db, student)
@app.get("/students/{student_id}", response_model=StudentResponse)
def get_student_endpoint(student_id: int, db: Session = Depends(get_db)):
student = get_student(db, student_id)
if not student:
raise HTTPException(status_code=404, detail="学生不存在")
return student
@app.get("/students", response_model=list[StudentResponse])
def get_all_students_endpoint(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
return get_all_students(db, skip, limit)
@app.put("/students/{student_id}", response_model=StudentResponse)
def update_student_endpoint(student_id: int, student: StudentCreate, db: Session = Depends(get_db)):
updated = update_student(db, student_id, student)
if not updated:
raise HTTPException(status_code=404, detail="学生不存在")
return updated
@app.delete("/students/{student_id}", status_code=204)
def delete_student_endpoint(student_id: int, db: Session = Depends(get_db)):
success = delete_student(db, student_id)
if not success:
raise HTTPException(status_code=404, detail="学生不存在")
return None