签入版本
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
# 同步编程模型
|
||||
|
||||
:::tip 核心原则
|
||||
Flask 基于 WSGI 同步框架,所有视图函数和业务代码均为同步 `def`。通过多线程/多进程实现并发,代码简洁直观,调试方便。
|
||||
:::
|
||||
|
||||
## Flask 的执行模型
|
||||
|
||||
Flask 采用同步编程模型,所有请求处理在独立的线程中执行:
|
||||
|
||||
```
|
||||
客户端请求
|
||||
↓
|
||||
WSGI 服务器(Gunicorn / Flask 内置)
|
||||
↓
|
||||
分配线程处理请求
|
||||
↓
|
||||
Flask 路由分发 → 视图函数 → Service → Repository → 数据库
|
||||
↓
|
||||
返回响应(同步等待完成)
|
||||
```
|
||||
|
||||
所有业务代码均为同步 `def`,数据库操作通过 SQLAlchemy 同步 ORM 完成,Redis 操作通过同步客户端完成。
|
||||
|
||||
## 为什么选择同步模型
|
||||
|
||||
| 考量 | 说明 |
|
||||
|:---|:---|
|
||||
| **成熟稳定** | Flask 同步模型经过长期验证,生态完善 |
|
||||
| **代码简洁** | 直接调用,无异步包装开销 |
|
||||
| **调试方便** | 标准 Python 调试工具(pdb)直接可用 |
|
||||
| **学习曲线** | 同步编程更直观,团队上手快 |
|
||||
| **后台管理** | CRUD 为主的场景,同步模型完全够用 |
|
||||
|
||||
## 代码示例:全同步模式
|
||||
|
||||
### Router 层
|
||||
|
||||
```python
|
||||
# src/modules/system/position/router.py
|
||||
from flask import Blueprint, request
|
||||
|
||||
from src.core.permission import check_permission
|
||||
from src.modules.system.position import service as position
|
||||
from src.common.utils.request import parse_request_body
|
||||
from src.core import response as R
|
||||
|
||||
position_blue = Blueprint('position', __name__, url_prefix='/position')
|
||||
|
||||
|
||||
@position_blue.route('/page', methods=["GET"])
|
||||
@check_permission("sys:position:page")
|
||||
def page():
|
||||
"""
|
||||
查询岗位分页数据
|
||||
|
||||
同步函数:直接调用 service,无需 await。
|
||||
"""
|
||||
return R.ok(data=position.get_position_page(request.args))
|
||||
|
||||
|
||||
@position_blue.route('/add', methods=["POST"])
|
||||
@check_permission("sys:position:add")
|
||||
def add():
|
||||
"""
|
||||
添加岗位
|
||||
|
||||
同步函数:解析请求体 → 调用 service → 返回结果。
|
||||
"""
|
||||
json_data, err = parse_request_body()
|
||||
if err:
|
||||
return R.failed(msg=err)
|
||||
position.add_position(json_data)
|
||||
return R.ok(msg="添加成功")
|
||||
```
|
||||
|
||||
### Service 层
|
||||
|
||||
```python
|
||||
# src/modules/system/position/service.py
|
||||
from src.common.base_service import BaseService
|
||||
from src.core.exceptions import BizError
|
||||
from src.modules.system.position.schema import PositionForm, PositionStatusForm
|
||||
from src.modules.system.position.repository import PositionRepository
|
||||
from src.modules.system.user.repository import UserRepository
|
||||
|
||||
|
||||
class PositionService(BaseService):
|
||||
"""
|
||||
岗位服务类
|
||||
|
||||
所有方法均为同步 classmethod,直接调用 Repository 访问数据库。
|
||||
"""
|
||||
repository = PositionRepository
|
||||
form = PositionForm
|
||||
status_form = PositionStatusForm
|
||||
model_name = "岗位"
|
||||
|
||||
@classmethod
|
||||
def before_delete(cls, ids):
|
||||
"""删除前校验:检查用户引用"""
|
||||
for pid in ids:
|
||||
if UserRepository.count_by({'position_id': pid}) > 0:
|
||||
raise BizError(f"岗位ID {pid} 已被用户引用,无法删除")
|
||||
|
||||
|
||||
# 模块级代理函数
|
||||
get_position_page = PositionService.get_page
|
||||
add_position = PositionService.add
|
||||
```
|
||||
|
||||
### Repository 层
|
||||
|
||||
```python
|
||||
# src/modules/system/position/repository.py
|
||||
from src.common.base_repository import BaseRepository
|
||||
from src.common.constants.common import PAGE_SIZE
|
||||
from src.modules.system.position.models import Position
|
||||
|
||||
|
||||
class PositionRepository(BaseRepository):
|
||||
"""岗位数据仓储,所有查询方法均为同步 classmethod"""
|
||||
model = Position
|
||||
|
||||
@classmethod
|
||||
def page(cls, params: dict):
|
||||
"""分页查询:直接调用基类 find_page,同步执行"""
|
||||
return cls.find_page(
|
||||
page=int(params.get('pageNo', 1)),
|
||||
page_size=int(params.get('pageSize', PAGE_SIZE)),
|
||||
filters={'status': params.get('status')},
|
||||
like_filters={'name': params.get('name')},
|
||||
order_by='sort',
|
||||
)
|
||||
```
|
||||
|
||||
:::tip 全链路同步
|
||||
从 Router → Service → Repository → 数据库,全链路均为同步调用,代码简洁直观。
|
||||
:::
|
||||
|
||||
## Redis 操作也是同步的
|
||||
|
||||
项目使用 `redis-py` 同步客户端,所有 Redis 操作也是同步的:
|
||||
|
||||
```python
|
||||
# src/core/redis_client.py
|
||||
from redis import Redis
|
||||
|
||||
redis = Redis.from_url(REDIS_URL, decode_responses=True)
|
||||
```
|
||||
|
||||
```python
|
||||
# 使用示例(同步)
|
||||
from src.core.redis_client import redis
|
||||
|
||||
# 存储验证码
|
||||
redis.set(f"captcha:{key}", code, ex=300)
|
||||
|
||||
# 查询验证码
|
||||
cached_code = redis.get(f"captcha:{key}")
|
||||
|
||||
# 登录失败计数
|
||||
count = redis.incr(f"login:fail:{ip}:{username}")
|
||||
redis.expire(f"login:fail:{ip}:{username}", 300)
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
项目采用 Flask 同步架构,全链路(Router → Service → Repository → Redis → 数据库)均为同步 `def`,代码简洁直观。通过 WSGI 服务器的多线程/多进程模型实现并发处理,对于后台管理系统场景完全够用。
|
||||
Reference in New Issue
Block a user