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 -323
View File
@@ -1,327 +1,8 @@
"""
命名格式转换工具模块
兼容 shim(绞杀者迁移期间保留)
=============================================================
提供字符串命名格式之间的转换功能,主要用于数据库字段名(下划线命名)
与前端字段名(驼峰命名)之间的转换。
主要功能:
1. 下划线命名 → 驼峰命名
2. 驼峰命名 → 下划线命名
3. 下划线命名 → 帕斯卡命名(大驼峰)
4. 递归转换字典的所有键名
命名转换工具已迁移至 src.common.utils.case_converter。
本文件仅作兼容转发,最终在 P7(切尾)阶段删除。
"""
def convert_camel_case(snake_str):
"""
将下划线命名转换为驼峰命名
Args:
snake_str: 下划线命名字符串,如 'create_time'
Returns:
驼峰命名字符串,如 'createTime'
Examples:
>>> convert_camel_case('create_time')
'createTime'
>>> convert_camel_case('user_id')
'userId'
>>> convert_camel_case('id')
'id'
>>> convert_camel_case('')
''
"""
if not snake_str:
return ''
components = snake_str.split('_')
return components[0] + ''.join(_capitalize_first_letter(x) for x in components[1:])
def convert_snake_case(camel_str):
"""
将驼峰命名转换为下划线命名
Args:
camel_str: 驼峰命名字符串,如 'createTime'
Returns:
下划线命名字符串,如 'create_time'
Examples:
>>> convert_snake_case('createTime')
'create_time'
>>> convert_snake_case('userId')
'user_id'
>>> convert_snake_case('id')
'id'
>>> convert_snake_case('')
''
"""
if not camel_str:
return ''
result = []
for i, char in enumerate(camel_str):
if char.isupper() and i > 0:
result.append('_')
result.append(char.lower())
else:
result.append(char.lower())
return ''.join(result)
def convert_pascal_case(snake_str):
"""
将下划线命名转换为帕斯卡命名(大驼峰)
Args:
snake_str: 下划线命名字符串,如 'create_time'
Returns:
帕斯卡命名字符串,如 'CreateTime'
Examples:
>>> convert_pascal_case('create_time')
'CreateTime'
>>> convert_pascal_case('user_id')
'UserId'
>>> convert_pascal_case('')
''
"""
if not snake_str:
return ''
components = snake_str.split('_')
return ''.join(_capitalize_first_letter(x) for x in components)
def convert_dict_keys(data, converter=convert_camel_case):
"""
递归转换字典的所有键名
Args:
data: 需要转换的字典或列表
converter: 转换函数,默认为 to_camel_case
Returns:
转换后的字典或列表
Examples:
>>> data = {'create_time': '2024-01-01', 'user_id': 1}
>>> convert_dict_keys(data)
{'createTime': '2024-01-01', 'userId': 1}
>>> data = [{'user_name': '张三'}, {'user_name': '李四'}]
>>> convert_dict_keys(data)
[{'userName': '张三'}, {'userName': '李四'}]
"""
if isinstance(data, list):
return [convert_dict_keys(item, converter) for item in data]
if isinstance(data, dict):
result = {}
for key, value in data.items():
new_key = converter(key)
result[new_key] = convert_dict_keys(value, converter)
return result
return data
def convert_snake_to_camel(data):
"""
将字典中的下划线命名字段转换为驼峰命名(便捷方法)
这是 convert_dict_keys 的便捷封装,专门用于数据库字段转前端字段。
Args:
data: 需要转换的字典或列表
Returns:
转换后的字典或列表(所有键名转为驼峰命名)
Examples:
>>> data = {'create_time': '2024-01-01', 'user_id': 1}
>>> convert_dict_keys_snake_to_camel(data)
{'createTime': '2024-01-01', 'userId': 1}
>>> data = [{'user_name': '张三'}, {'user_name': '李四'}]
>>> convert_dict_keys_snake_to_camel(data)
[{'userName': '张三'}, {'userName': '李四'}]
"""
return convert_dict_keys(data, converter=convert_camel_case)
def convert_camel_to_snake(data):
"""
将字典中的驼峰命名字段转换为下划线命名(便捷方法)
这是 convert_dict_keys 的便捷封装,专门用于前端字段转数据库字段。
Args:
data: 需要转换的字典或列表
Returns:
转换后的字典或列表(所有键名转为下划线命名)
Examples:
>>> data = {'createTime': '2024-01-01', 'userId': 1}
>>> convert_dict_keys_camel_to_snake(data)
{'create_time': '2024-01-01', 'user_id': 1}
>>> data = [{'userName': '张三'}, {'userName': '李四'}]
>>> convert_dict_keys_camel_to_snake(data)
[{'user_name': '张三'}, {'user_name': '李四'}]
"""
return convert_dict_keys(data, converter=convert_snake_case)
# ============================================================
# 私有方法
# ============================================================
def _capitalize_first_letter(s):
"""
将字符串的首字母大写,其余字母小写
Args:
s: 输入字符串
Returns:
首字母大写后的字符串
Examples:
>>> _capitalize_first_letter('name')
'Name'
>>> _capitalize_first_letter('userName')
'Username'
>>> _capitalize_first_letter('')
''
"""
if not s:
return ''
return s[0].upper() + s[1:].lower()
def _is_camel_case(s):
"""
判断字符串是否为驼峰命名格式
驼峰命名特征:
1. 首字母小写
2. 不包含下划线
3. 包含大写字母(至少一个大写字母)
Args:
s: 输入字符串
Returns:
bool: 是否为驼峰命名格式
Examples:
>>> _is_camel_case('createTime')
True
>>> _is_camel_case('create_time')
False
>>> _is_camel_case('id')
False
"""
if not s:
return False
# 首字母必须小写,不包含下划线,且至少有一个大写字母
return (s[0].islower() and
'_' not in s and
any(char.isupper() for char in s))
def _is_snake_case(s):
"""
判断字符串是否为下划线命名格式
下划线命名特征:
1. 全部小写
2. 包含下划线
3. 不以_开头,不以_结尾
Args:
s: 输入字符串
Returns:
bool: 是否为下划线命名格式
Examples:
>>> _is_snake_case('create_time')
True
>>> _is_snake_case('createTime')
False
>>> _is_snake_case('id')
False
"""
if not s:
return False
# 全部小写,包含下划线,且不以_开头结尾
return (s.islower() and
'_' in s and
not s.startswith('_') and
not s.endswith('_'))
def _is_pascal_case(s):
"""
判断字符串是否为帕斯卡命名格式(大驼峰)
帕斯卡命名特征:
1. 首字母大写
2. 不包含下划线
3. 至少有一个字母
Args:
s: 输入字符串
Returns:
bool: 是否为帕斯卡命名格式
Examples:
>>> _is_pascal_case('CreateTime')
True
>>> _is_pascal_case('createTime')
False
>>> _is_pascal_case('create_time')
False
"""
if not s:
return False
# 首字母大写,不包含下划线
return (s[0].isupper() and
'_' not in s and
any(char.isalpha() for char in s))
def _convert_single_field(field_name, converter=convert_camel_case):
"""
转换单个字段名
Args:
field_name: 字段名
converter: 转换函数,默认为 to_camel_case
Returns:
转换后的字段名
Examples:
>>> _convert_single_field('create_time')
'createTime'
>>> _convert_single_field('createTime', convert_snake_case)
'create_time'
"""
if not field_name:
return ''
return converter(field_name)
from src.common.utils.case_converter import * # noqa: F401,F403