FastAPI分层架构实战:高效API开发指南
1.路径讲解
boss-api/ ├── main.py # FastAPI应用主入口 │ ├── requirements.txt # Python依赖包 │ └── app/ # 应用核心代码 ├── __init__.py │ │ ├── models/ # 数据模型层 (Tortoise ORM) │ ├── __init__.py │ ├── user.py # 用户相关模型 │ ├── apis/ # API路由层[接受参数,返回数据] │ ├── __init__.py │ └── user_api.py # 用户相关API │ └── schemas/ # 数据验证层 (Pydantic) │ ├── __init__.py │ └── user.py # 用户请求/响应模型 │ │ ├── services/ # 业务服务层 (逻辑) │ ├── __init__.py │ ├── user.py # 用户相关的业务代码/方法 │ │ ├── core/ # 核心文件 │ ├── __init__.py │ ├── database.py # 数据库连接信息 ├── config/ # 配置文件 │ ├── __init__.py │ ├── settings.py # 多环境配置2.区别
我们将昨天的写法改变了一下
1.昨天是
模型写在models文件下 路由和方法都写再routers中 而请求体写在schemas中
在main主路由下调用 day02下routers中的方法来完成的
2.今天我们将路由和方法分开写入
apis只写我们的路由方法 如下
@day03_user_api.post("/") async def login(username: str, password: str): code, message = await user.login(username, password) return {"code": code, "message": message}我们走的是post添加的接口 在下面走我们 services中的user.py 也就是我们的方法
from day02.models.book import User async def login(username: str, password: str): user = await User.filter(username=username).first() if not user: return 404, "用户不存在" if user.password_hash == password: return 400, "登录成功" return 404,"密码错误"从我们路由apis user 中传到 services 然后使用我们的方法 进行正常的流程
我们return返回要于我们路由中相等 code,msg,data
return 404,"密码错误",None
路由中用 code,msg,data 接受然后再用字典的方法输出
code, message = await user.login(username, password)
return {"code": code, "message": message}我们将所有的全部分开单独写一个文件 这样方便我们查找 不会混乱
3.查询
1. 从A表查询B表 B表有A表的外键
- 科室列表:展示所有科室,显示科室名称、楼栋、楼层、医生数量
从我们的科室列表 每个科室下都有哪些医生:
async def get_departments(): # related_name 是 doctors,预加载关联医生列表 departments = await Department.all().prefetch_related("doctors") departments_list = [] for department in departments: # 遍历当前科室下所有医生 doctor_list = [ { "id": doctor.id, "name": doctor.name, "title": doctor.title, "specialty": doctor.specialty, "phone": doctor.phone, "daily_quota": doctor.daily_quota, "status": doctor.status, "created_at": doctor.created_at, "updated_at": doctor.updated_at } for doctor in department.doctors ] departments_list.append({ "id": department.id, "name": department.name, "building": department.building, "floor": department.floor, "description": department.description, "Doctor": doctor_list # 一个科室对应多个医生,数组 }) return 200, "获取成功", departments_list我们先查询所有的科室关联我们的doctors表
departments = await Department.all().prefetch_related("doctors")定义一个我们要返回的列表 departments_list = []
循环遍历我们的departments 每条数据赋值给department
在根据我们的科室id去查找我们的医生表 历当前科室下所有医生
在下面输出我们的科室信息 append加入我们的医生表 一个科室对应多个医生,数组
最后返回给路由
科室id=1 下有医生id=1,2等
2.从一个表查我们的外键表
- 管理联系方式:在患者列表中点击"联系方式",可查看/创建/编辑该患者的一对一联系方式(手机号、微信、邮箱、紧急联系人、住址)
async def get_patient(id): patient = await Patient.get_or_none(id=id).prefetch_related("contact") if not patient: return 404, "患者不存在", None # 安全处理:防止没有contact时报错 contact_info = None if hasattr(patient, "contact") and patient.contact: contact_info = { "phone": patient.contact.phone, "wechat": patient.contact.wechat, "email": patient.contact.email, "contact_name": patient.contact.contact_name, "contact_phone": patient.contact.contact_phone, "address": patient.contact.address, } patient_data = { "id": patient.id, "name": patient.name, "gender": patient.gender, "age": patient.age, "id_card": patient.id_card, "created_at": patient.created_at, "updated_at": patient.updated_at, "contact": contact_info } return 200, "获取成功", patient_data从患者表 查询患者的信息资料
patient = await Patient.get_or_none(id=id).prefetch_related("contact") if not patient: return 404,“患者不存在",None先查询id时候存在 预加载 contact
然后定义一个用来返回的空列表 上面是我们当前患者 下面是我们的患者信息资料
先查找我们id对应的患者资料
if hasattr(patient, "contact") and patient.contact: contact_info = { "phone": patient.contact.phone, "wechat": patient.contact.wechat, "email": patient.contact.email, "contact_name": patient.contact.contact_name, "contact_phone": patient.contact.contact_phone, "address": patient.contact.address, }是我们的详细资料然后加到我们的患者表中
patient_data = { "id": patient.id, "name": patient.name, "gender": patient.gender, "age": patient.age, "id_card": patient.id_card, "created_at": patient.created_at, "updated_at": patient.updated_at, "contact": contact_info }"contact": contact_info 是我们的详细治疗 我们上面已经定义出来 直接加到我们的患者表就可以了
上面是信息 下面是治疗 这是1对1 查询
