FastAPI实战(第二部分):用户注册接口开发详解

一、项目结构解析

这是一个典型的 FastAPI 项目,采用分层架构,核心目录如下:

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| toutiao_backend/ ├── config/ # 配置层 │ └── db_conf.py # 数据库配置(异步引擎、会话、依赖项) ├── crud/ # 业务逻辑层(CRUD 操作) ├── models/ # 数据模型层(SQLAlchemy ORM) ├── routers/ # 路由层(API 接口) │ ├── news.py │ └── users.py # 用户相关接口(当前编辑文件) ├── schemas/ # 数据校验层(Pydantic 模型) ├── utils/ # 工具函数层 ├── main.py # 项目入口(FastAPI 实例、路由注册) └── venv/ # 虚拟环境 |

二、核心代码结构化输出

1. 数据库配置( config/db_conf.py

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession from sqlalchemy.orm import DeclarativeBase # 异步数据库连接 URL(示例,需根据实际环境修改) ASYNC_DATABASE_URL = "mysql+aiomysql://root:password@localhost:3306/toutiao_backend?charset=utf8" # 创建异步引擎 async_engine = create_async_engine( ASYNC_DATABASE_URL, echo=True, pool_size=10, max_overflow=20 ) # 创建异步会话工厂 AsyncSessionLocal = async_sessionmaker( bind=async_engine, class_=AsyncSession, expire_on_commit=False ) # 定义 ORM 模型基类 class Base(DeclarativeBase): pass # 数据库会话依赖项 async def get_db(): async with AsyncSessionLocal() as session: try: yield session await session.commit() except Exception: await session.rollback() raise finally: await session.close() |

2. 用户路由( routers/users.py

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from fastapi import APIRouter, Depends from sqlalchemy.ext.asyncio import AsyncSession from config.db_conf import get_db # 定义 APIRouter 实例 router = APIRouter( prefix="/api/user", # 路由前缀 tags=["users"] # 接口文档标签 ) # 用户注册接口 @router.post("/register") async def register( db: AsyncSession = Depends(get_db) # 注入数据库会话 ): # 模拟返回注册成功的响应 return { "code": 200, "message": "注册成功", "data": { "token": "用户访问令牌", "userInfo": { "id": 1, "username": "example_user", "bio": "这个人很懒,什么都没留下", "avatar": "https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" } } } |

3. 项目入口( main.py

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from fastapi import FastAPI from routers import users, news # 导入路由模块 # 创建 FastAPI 实例 app = FastAPI(title="头条后端 API", version="1.0") # 注册子路由 app.include_router(users.router) app.include_router(news.router) # 启动事件:自动创建数据库表 @app.on_event("startup") async def startup_event(): from config.db_conf import async_engine, Base async with async_engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) |

三、核心代码实现如下:

  1. model/user.py文件中,建立模型类User,通过用户表ORM模型实现:
python 复制代码
from sqlalchemy import String, Integer, DateTime, Text, Boolean
from sqlalchemy.orm import Mapped, mapped_column
from datetime import datetime
from config.db_conf import Base  # 导入项目定义的 ORM 基类

class User(Base):
    """用户表 ORM 模型,映射数据库 user 表"""
    __tablename__ = "user"  # 数据库表名(必须与实际表名一致)

    # 核心字段定义(Mapped 类型注解 + mapped_column 字段属性)
    id: Mapped[int] = mapped_column(
        Integer, primary_key=True, autoincrement=True, comment="用户唯一ID"
    )
    username: Mapped[str] = mapped_column(
        String(50), unique=True, nullable=False, comment="用户名(唯一)"
    )
    password: Mapped[str] = mapped_column(
        String(128), nullable=False, comment="加密后的密码(不可明文存储)"
    )
    email: Mapped[str] = mapped_column(
        String(100), unique=True, nullable=False, comment="邮箱(唯一,用于登录/找回密码)"
    )
    phone: Mapped[str | None] = mapped_column(
        String(20), unique=True, nullable=True, comment="手机号(可选,唯一)"
    )
    avatar: Mapped[str | None] = mapped_column(
        String(255), nullable=True, default="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg", comment="用户头像URL"
    )
    bio: Mapped[str | None] = mapped_column(
        Text, nullable=True, default="这个人很懒,什么都没留下", comment="个人简介"
    )
    is_active: Mapped[bool] = mapped_column(
        Boolean, default=True, comment="账号是否激活(True=正常,False=禁用)"
    )
    is_admin: Mapped[bool] = mapped_column(
        Boolean, default=False, comment="是否为管理员(True=管理员,False=普通用户)"
    )
    create_time: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.now, comment="账号创建时间"
    )
    update_time: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.now, onupdate=datetime.now, comment="账号更新时间"
    )

    def __repr__(self):
        """实例打印格式化(便于调试)"""
        return f"<User(id={self.id}, username='{self.username}', email='{self.email}')>"
  1. crud****/users.py****中,建立两个函数:一是根据用户名查数据库;二是创建用户;
python 复制代码
根据用户名查询数据库
async def get_user_by_username (db: AsyncSession, username: str) :
query = select(User).where(User.username == username)
result = await db.execute(query)
return result.scalar_one_or_none()
创建用户
async def create_user(db: AsyncSession, user_data: UserRequest):
#先密码加密处理>add
hashed_password = security.get_hash_password (user_data.password)user = User(username=user_data.username, password=hashed_password)db.add(user)
await db.commit()
await db.refresh(user) #从数据库读回最新的 user
returnuser
  1. routers/users.py文件中,编写register函数,实现创建用户和检查用户是否存在;
python 复制代码
@router.post("/register")
async def register(user data: UserRequest, db: AsyncSession = Depends(get_db)) : 
# 用户信息注册逻辑:验证用户是否存在->创建用户 >生成Token >响应结果
existing_User = await users.get_user_by_username(db, user_data.Username
if existing_user:raise HTTPException(status_code=status.HTTP _400_BAD_REQUEST, detail="用户已存在")

User = await users.create_user(db, User_data)
return {
"code":200
'message":"注册成功",
'data":{
"token":"用户访问令牌",
"userInfo": {
"id": user.id,
"username": user.Username,
"bio":user.bio,
"avatar": [https://fastly.jsdeliyr.net/npm/@vant/assets/cat.jpeg"
}
}
}
  1. crud****/users.py,创建create_token****函数,生成访问令牌token,具体流程如下:
python 复制代码
#生成Token
asyncdef create_token(db: AsyncSession, user_id: int):
#生成Token+设置过期时间查询数据库当前用户是否有Token有:更新;没有:添加#
token = str(uuid.uuid4())
# timedelta(days=7, hours=2, minutes=30, seconds=10)expires_at = datetime.now() + timedelta(days=7)query = select(UserToken).where(UserToken.user_id == user_id)result = await db.execute(query)user_token = result.scalar_one_or_none()
if user_token:
user_token.token = token
user_token.expires_at = expires_at
else:
user_token = UserToken(user_id=user_id, token=token,expires_at=expires_at)
db.add(user_token)
await db.commit()
return token
  1. routers/users.py文件中,编写register的create_token函数;
python 复制代码
@router.post("/register")
async def register(user _data: UserRequest, db: AsyncSession = Depends(get_db)): # 用户信息 和 db
#注册逻辑:验证用户是否存在-> 创建用户 >生成Token >响应结果existing_user = await users.get_user_by_username(db, user_data.Username)if existing_user:
HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="用户已存在")raise
User = await Users.create_user(db, User_data)
token = await users.create_token(db, user.id)
return {
"code": 200
"message":"注册成功",

"data":{
"token": token,
"userInfo": {
"id": user.id,
"username": user.username
"bio": user.bio,
'avatar": user.avatar
}}}
  1. 封装UserInfoResponse类;UserAuthResponse中包含UserInfoResponse类,
python 复制代码
class UserRequest(BaseModel):
username:str
password:str
#user_info 对应的类:基础类+Info类(id、用户名)#

#userinfo第一个数据类型定义:
class UserInfoBase(BaseModel):
#用户信息基础数据模型
nickname:Qpt onal[str] = Field(None, max_length=50, description="昵称")avatar: Qeti0al[str] = Field(None, max_length=255, description="头像URL")gender: Qptional[str] = Field(None, max_length=10, description="性别!")bio: Qptional[str] = Field(None, max_length=500, description="个人简介")

#userinfo第二个数据类型定义:
class UserInfoResponse(UserInfoBase):
id: int
username: str
# 模型类配置
model_config = ConfigDict(
from_attributes=True # 允许从 ORM 对象属性中取值


#data数据类型要求如下:
class UserAuthResponse(BaseModel):
token: str
User_info: UserInfoResponse = Field(..., alias="userInfo")
#模型类配置
model_config = ConfigDict(
populate_by_name=True,#alias/字段名兼容from_attributes
}
  1. 重新写register的返回数据类型response_data,调用封装好的类 UserAuthResponse。
python 复制代码
@router.post("/register")
async def register(user _data: UserRequest, db: AsyncSession = Depends(get_db)): # 用户信息 和 db
#注册逻辑:验证用户是否存在-> 创建用户 >生成Token >响应结果existing_user = await users.get_user_by_username(db, user_data.Username)if existing_user:
HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="用户已存在")raise
User = await Users.create_user(db, User_data)
token = await users.create_token(db, user.id)
return {
"code": 200
"message":"注册成功",


response_data = UserAuthResponse(token=token, user_info=UseripfoResponse.model validate(user))
return success_response(message="注册成功", data=response_data)

****四、总结用户注册的接口开发流程

请求流入 :客户端请求 /api/user/register,由 users.py 中的 register 函数处理。

依赖注入 :通过 Depends(get_db) 自动创建并注入数据库会话 db,统一管理事务。

业务逻辑 :当前为模拟实现,实际开发中会调用 crud/ 层的函数,通过 models/ 中的 ORM 模型操作数据库。

响应返回:返回标准化的 JSON 响应,包含状态码、消息和用户数据。

相关推荐
星爷AG I1 小时前
12-6 心理理论(AGI基础理论)
人工智能·agi
向哆哆1 小时前
102类农业害虫图像识别数据集:智慧农业与精准防控的高质量资源
人工智能
lisw051 小时前
云原生技术概述!
人工智能·机器学习·云原生
小程故事多_801 小时前
深度解析个人AI助手OpenClaw:从消息处理到定时任务的全流程架构
人工智能·架构
开发者导航2 小时前
【开发者导航】多功能生成模型开发工具:Diffusers 详细介绍
人工智能·python·学习·macos·信息可视化
肾透侧视攻城狮2 小时前
《解锁TensorFlow模型潜力:超参数、网络结构、训练过程优化与高级技巧一站式精讲》
人工智能·深度学习·tensorflow 模型调优·静态/动态学习率·批量大小选择·宽/深度调整技巧·dropout/早停法
ん贤2 小时前
Scrapy 嵌入 FastAPI 的坑:Asyncio/Twisted 桥接 + 代理池设计
python·scrapy·fastapi
岱宗夫up2 小时前
从代码模式到智能模式:AI时代的设计模式进化论
开发语言·python·深度学习·神经网络·自然语言处理·知识图谱
xzjiang_3652 小时前
Jupyter 运行经验3:读入和显示一张图片
ide·python·jupyter