refactor: P2 core+common 建设(应用工厂/扩展/工具层迁入 src/)

【结构】
- src/core/:database/response/jwt/password/security/redis_client/mail/scheduler
- src/common/:base_model/base_db/forms(base_form+fields)/constants/utils
- src/models_registry.py:模型聚合器(Flask-Migrate 全量表识别)

【绞杀者 shim】extensions/、utils/、application/constants|forms|models 打兼容转发
【兼容修复】应用工厂抽取至 application/factory.py(P2 前置,P1 已完成)

【基线修复】application/models(25) + middleware(7) 原被嵌套 .gitignore(*)
误排除出版本库,已补入(base_model/base_db 现为 shim,原版在 src/common/)

【登记既有缺陷】
1. flask db CLI 因 .env FLASK_VERSION 与 --version 冲突报错 → Makefile 已加 FLASK_SKIP_DOTENV=1
2. 本机 Redis 未设密码但 REDIS_AUTH=True,/captcha 报 AUTH 错误(环境问题)

【验收】22 模型表全量识别;src/ flake8 零告警;pytest 5 passed;应用启动;
/login 表单校验、/user/page 鉴权拦截冒烟正常

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
DjangoAdmin Dev
2026-08-07 13:20:46 +08:00
co-authored by Claude
parent 92130ef070
commit 658ee6d596
96 changed files with 9926 additions and 4153 deletions
+4 -192
View File
@@ -1,196 +1,8 @@
"""
请求解析工具模块
兼容 shim(绞杀者迁移期间保留)
=============================================================
提供请求数据解析相关的工具函数:
- get_json_data: 从Flask请求中解析JSON数据
- require_json: 装饰器,要求请求必须包含JSON数据
- parse_request_body: 解析请求体JSON数据,返回(data, error)元组
- parse_id_list: 将逗号分隔的ID字符串解析为整数列表
- parse_batch_ids: 从请求体解析批量删除ID数组,校验并转为逗号分隔字符串
- like_escape: 转义SQL LIKE通配符,防止用户输入被当作通配符
- like_contains: 构建安全的LIKE包含查询值
请求解析工具已迁移至 src.common.utils.request。
本文件仅作兼容转发,最终在 P7(切尾)阶段删除。
"""
import logging
from functools import wraps
logger = logging.getLogger(__name__)
def get_json_data(required=True, silent=False):
"""
获取请求中的JSON数据
Args:
required: 是否必须获取到JSON数据,默认为True
silent: 是否静默处理错误,默认为False(False时会检查Content-Type)
Returns:
dict: JSON数据,如果获取失败则返回None或空字典
"""
from flask import request
if not silent and not request.is_json:
return None
try:
json_data = request.get_json(silent=silent)
except Exception:
return None
if required and not json_data:
return None
return json_data or {}
def require_json(f):
"""
装饰器:要求请求必须包含JSON数据
Examples:
@require_json
def login():
data = get_json_data()
# 业务逻辑...
"""
@wraps(f)
def decorated_function(*args, **kwargs):
from flask import request
if not request.is_json:
from utils import R
return R.failed(msg="参数格式不正确,请使用JSON格式")
json_data = request.get_json()
if not json_data:
from utils import R
return R.failed(msg="参数不能为空")
request.parsed_json = json_data
return f(*args, **kwargs)
return decorated_function
def parse_request_body():
"""
解析请求体JSON数据
Returns:
tuple: (data, error)
成功时 data 为解析后的字典,error 为 None
失败时 data 为 None,error 为错误描述字符串
"""
try:
data = get_json_data(required=False, silent=True)
if data is None or data == {}:
return None, "参数不能为空"
return data, None
except Exception as e:
logger.error(f"解析请求体异常: {str(e)}")
return None, "参数处理失败"
def parse_id_list(id_str: str, separator: str = ',') -> list:
"""
将逗号分隔的ID字符串解析为整数列表
Args:
id_str: 逗号分隔的ID字符串,如 "1,2,3"
separator: 分隔符,默认为逗号
Returns:
list: 有效的整数ID列表
Example:
>>> parse_id_list("1,2,3")
[1, 2, 3]
>>> parse_id_list("1,2,abc,3")
[1, 2, 3]
"""
if not id_str:
return []
result = []
for item in id_str.split(separator):
item = item.strip()
if item.isdigit():
result.append(int(item))
return result
def parse_batch_ids():
"""
从请求体解析批量删除的ID数组,校验并转为逗号分隔字符串
请求体格式: [1, 2, 3]
Returns:
tuple: (id_str, error_response)
成功时 id_str 为 "1,2,3",error_response 为 None
失败时 id_str 为 None,error_response 为 R.failed 响应
"""
from flask import request
from utils import R
ids = request.get_json()
if not ids or not isinstance(ids, list) or len(ids) == 0:
return None, R.failed("参数错误:ids必须为非空数组")
try:
id_list = [int(id_val) for id_val in ids]
except (ValueError, TypeError):
return None, R.failed("参数错误:数组元素必须为数字")
return ','.join(str(id_val) for id_val in id_list), None
def like_escape(value, escape_char='\\'):
"""
转义SQL LIKE通配符
将用户输入中的 %、_ 和转义字符本身进行转义,
防止用户输入被当作LIKE通配符导致非预期查询结果。
Args:
value: 原始输入值
escape_char: 转义字符,默认为反斜杠
Returns:
str: 转义后的安全字符串
Example:
>>> like_escape('100%')
'100\\%'
>>> like_escape('test_data')
'test\\_data'
"""
escaped = str(value).replace(escape_char, escape_char * 2)
escaped = escaped.replace('%', escape_char + '%')
escaped = escaped.replace('_', escape_char + '_')
return escaped
def like_contains(value, escape_char='\\'):
"""
构建安全的LIKE包含查询值(前后加%)
对用户输入进行通配符转义后,前后添加 % 构建模糊查询值。
配合 SQLAlchemy 的 .like() 方法和 escape 参数使用。
Args:
value: 原始输入值
escape_char: 转义字符,默认为反斜杠
Returns:
str: 构建好的LIKE查询值,如 '%safe_value%'
Example:
>>> # SQLAlchemy 用法
>>> query = query.filter(User.name.like(like_contains(name), escape='\\'))
"""
return f'%{like_escape(value, escape_char)}%'
from src.common.utils.request import * # noqa: F401,F403