一、项目介绍
1.1、项目背景
随着互联网普及,用户对新闻咨询获取有了更高的要求:快速、个性化、可追溯。传统新闻应用在响应速度、内容推荐和用户体验上存在一定的局限性。
1.2、项目目标
为了满足用户对新闻浏览、收藏、历史记录等核心场景需求。我们特地研发了这个项目。
1.3、项目架构
我们的项目基于FastAPI和SQLAlchemy构建,采用Starlette异步架构设计
1.4、项目功能
实现了用户注册、登录、新闻浏览、收藏和历史记录等全流程功能
分为了用户管理、新闻内容、点赞收藏、浏览历史四大核心模块
1.5、设计过程中遇到的问题
1.6、开发完怎么进行测试的(有没有分场景,写用例)
1.7、项目亮点,用到的核心技术
二、业务详细流程
2.1用户管理模块
用户注册
业务流程:
用户进入登录注册页面,如果用户有账号,直接登录,没有账号,进入注册流程:
用户输入用户名和密码,后端会先通过Pydantic验证数据模型,不通过报错,通过后,再查询用户名是否存在,如果存在,提示用户名已经存在,如果不存在
①将创建用户,创建用户这里我们是封装了一个方法到curd包下面。传递用户数据,包含用户名和密码,这样方法首先拿到密码进行argon2哈希加密算法加密。接着创建一个SQLAlchemy ORM 用户对象。把它添加到数据库中,提交并,刷新,拿到包含 User 模型定义的所有字段并返回
②创建访问令牌token,也是封装了一个方法放在了curd包下面,传入用户 id 来为该用户创建访问令牌。该方法首先生成一个 UUID 格式的随机访问令牌,并设置令牌 7 天的有效期,接着根据用户id查询该用户是否已有令牌记录,如果已有令牌记录,就更新令牌内容和过期时间;如果没有令牌记录,就创建一个新的 UserToken ORM 对象,包含用户 id、新生成的令牌和过期时间,将其添加到数据库并提交,最后返回生成的访问令牌(返回的 token 无 Bearer 前缀)。
将生成的访问令牌和用户信息封装到字典类型的 response_data 中,通过 success_response 返回给前端,同时提示 "登录成功"。

用户登录
业务流程:
如果用户有账号,进入登录流程:
用户输入用户名和密码,后端会先通过Pydantic验证数据模型,不通过报错,通过后,首先
①调用校验方法验证用户信息,传入用户名和密码,该方法先根据用户名查询数据库获取用户对象,如果查询不到用户,直接返回用户名或密码错误;如果查询到用户,
再调用验证密码的方法,传入用户输入的密码和在数据库查到的密码。进行校验。如果:若用户信息验证失败,直接抛出异常提示 "用户名或密码错误";若验证成功,则
②调用创建访问令牌的方法(封装在 curd 包下)得到令牌,该方法通过传入用户 id 来为该用户创建访问令牌。该方法首先生成一个 UUID 格式的随机访问令牌,并设置令牌 7 天的有效期,接着根据用户id查询该用户是否已有令牌记录,如果已有令牌记录,就更新令牌内容和过期时间;如果没有令牌记录,就创建一个新的 UserToken ORM 对象,包含用户 id、新生成的令牌和过期时间,将其添加到数据库并提交,最后返回生成的访问令牌(返回的 token 无 Bearer 前缀)。
将生成的访问令牌和用户信息封装到字典类型的 response_data 中,通过 success_response 返回给前端,同时提示 "登录成功"。

获取用户信息
用户在已登录状态下触发获取用户信息操作(如进入个人中心),后端开始处理获取用户信息的请求:
前端在请求头的 authorization 字段中携带包含 Bearer 前缀的令牌信息,后端
①首先从该字段中提取出纯令牌字符串(去除 Bearer 前缀)。接着
②调用通过令牌查询用户信息的方法(封装在 curd 包下),该方法首先根据令牌字符串查询数据库中的 UserToken 表,获取对应的令牌记录:
- 如果未查询到令牌记录,或查询到的令牌记录其过期时间早于当前时间(令牌已过期),则返回空值;
- 如果查询到有效的令牌记录(存在且未过期),则提取该记录中的 user_id,再通过 user_id 查询数据库中的 User 表,获取完整的用户对象并返回。
③若通过令牌未查询到有效的用户信息(返回空值),后端直接抛出异常提示 "用户没有登录";若查询到有效的用户对象,先将用户对象转换为可序列化的 JSON 格式数据,再将该用户信息封装到字典类型的 data 中,通过 success_response 返回给前端,同时提示 "获取用户信息成功"。

更新用户信息
用户在已登录状态下触发更新用户信息操作(如修改个人资料),后端会先通过Pydantic验证数据模型,不通过报错,通过后,后端开始处理更新用户信息的请求:
前端在请求头的 authorization 字段中携带包含 Bearer 前缀的令牌信息,同时传递需要更新的用户信息数据(如昵称、手机号等),后端首先
①调用通过令牌查询用户信息的方法,校验用户是否处于登录状态:
若未查询到有效的用户信息(令牌不存在、过期或关联不到用户),直接抛出异常提示 "用户没有登录";
若校验通过,获取到当前登录的用户对象,
②调用更新用户信息的方法(封装在 curd 包下),传入待更新的用户信息、数据库会话和当前用户对象。
该更新方法首先将前端传递的更新数据转换为字典格式,并过滤掉未设置、值为 None 的属性(仅保留需要实际更新的字段);接着通过属性赋值的方式,逐个将新值更新到当前用户对象对应的字段上;更新完成后提交数据库事务,再刷新用户对象(重新从数据库获取最新的用户数据),确保返回的用户信息是最新状态。
最终将更新后的用户对象封装到字典类型的 data 中,通过 success_response 返回给前端,同时提示 "更新用户信息成功"。

修改用户密码
修改用户密码流程描述
用户在已登录状态下触发修改密码操作,后端会先通过Pydantic验证数据模型,不通过报错,通过后,后端开始处理修改用户密码的请求:
前端在请求头的 authorization 字段中携带包含 Bearer 前缀的令牌信息,同时传递旧密码和新密码数据,后端首先执行以下校验步骤:
①调用通过令牌查询用户信息的方法,校验用户是否处于登录状态:若未查询到有效的用户信息(令牌不存在、过期或关联不到用户),直接抛出异常提示 "用户没有登录";若校验通过,获取到当前登录的用户对象。
②调用用户信息校验方法,传入当前用户的用户名和前端提交的旧密码:先根据用户名查询用户对象(确保用户存在),再使用 argon2 哈希加密算法对应的校验方法,对比旧密码明文与数据库中存储的哈希密码是否一致,若不一致则抛出异常提示 "旧密码错误";若校验通过,返回当前用户对象。
校验全部通过后,
③调用修改用户密码的方法(封装在 curd 包下),传入新密码、数据库会话和当前用户对象:该方法首先使用 argon2 哈希加密算法对新密码进行哈希处理,再通过 SQLAlchemy 的 Update 语句,根据用户 id 更新数据库中该用户的密码字段为加密后的新密码;更新完成后提交数据库事务,再刷新用户对象(重新从数据库获取最新的用户数据),确保返回的用户信息是最新状态。
最终将更新后的用户对象封装到字典类型的 data 中,通过 success_response 返回给前端,同时提示 "修改用户密码成功"。
