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 响应,包含状态码、消息和用户数据。

相关推荐
科技社7 分钟前
咪咕互娱亮相数字中国峰会:“精品游戏+轻量终端”组合,打开数字娱乐新想象
人工智能
m0_4954964135 分钟前
mysql处理复杂SQL性能_InnoDB优化器与MyISAM差异
jvm·数据库·python
数智化精益手记局1 小时前
拆解物料管理erp系统的核心功能,看物料管理erp系统如何解决库存积压与缺料难题
大数据·网络·人工智能·安全·信息可视化·精益工程
Flying pigs~~1 小时前
RAG 完整面试指南:原理、优化、幻觉解决方案
人工智能·prompt·rag·智能体·检索增强生成·rag优化
博.闻广见1 小时前
AI_概率统计-2.常见分布
人工智能·机器学习
企业架构师老王1 小时前
2026制造业安全生产隐患识别AI方案:从主流产品对比看企业级AI Agent的非侵入式落地路径
人工智能·安全·ai
forEverPlume1 小时前
PHP怎么使用Eloquent Attribute Composition属性组合_Laravel通过组合构建复杂属性【方法】
jvm·数据库·python
Aleeeeex1 小时前
RAG 那点事:从 8 份企业文档到能用的问答系统,全过程拆给你看
人工智能·python·ai编程
冬奇Lab2 小时前
一天一个开源项目(第87篇):Tank-OS —— Red Hat 工程师用一个周末,把 AI Agent 塞进了一个可启动的 Linux 镜像
人工智能·开源·资讯
小糖学代码2 小时前
LLM系列:2.pytorch入门:8.神经网络的损失函数(criterion)
人工智能·深度学习·神经网络