初始化项目

This commit is contained in:
zwf
2026-06-02 17:46:38 +08:00
commit 646a4d02c0
240 changed files with 33662 additions and 0 deletions
+183
View File
@@ -0,0 +1,183 @@
import datetime
import json
import os
from abc import ABC
from typing import Optional, Callable, Awaitable
from paste.rbac.rbac_user import RbacUser
from paste.util.encoder import JsonDumpsEncoder
from paste.web.handler import RequestHandler
from paste.web.param_aware_loader import ParamAwareLoader
class AppHandler(RequestHandler, ABC):
"""
控制器基类。
"""
commands: dict[str, Callable] = {}
"""
API 接口命令字典,其结构为命令名称指向对应的方法。
其结构如下::
{
command_name: method
}
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user: Optional[RbacUser] = None
"""
当前登录用户对象。
"""
self.start_at = datetime.datetime.now()
"""
实例初始化时间。
"""
self.command = ""
"""
命令。
"""
self.request_params = {}
"""
命令参数。
"""
async def after_auth_token(self, token_payload: dict):
"""
初始化登录用户信息。
"""
from paste.security import token
if token_payload != token.PRIVATE_ISS:
from jwt import InvalidTokenError
raise InvalidTokenError()
async def run_command(self):
"""
根据请求参数运行命令方法,返回命令执行结果。
"""
self.get_request_params()
assert self.command in self.commands, '请提供正确的命令参数.'
# 读取命令方法对象,并执行
_cmd_func = self.commands[self.command]
_result = _cmd_func(self, **self.request_params)
# 处理异步方法执行
if isinstance(_result, Awaitable):
_result = await _result
return _result
async def gen_html(self, template_file: str, **kwargs):
"""
生成 HTML 内容。
:param template_file: 模板文件
:param kwargs: 参数数据字典
:return: 返回生成的 HTML 文件内容
"""
# 将参数字典转换为 namedtuple,名称固定
template_data_obj = self.dict_to_namedtuple('TemplateData', {**kwargs})
# 手动构建完整命名空间,加入自定义参数,传给生成器
namespace = self.get_template_namespace()
namespace.update({'td': template_data_obj})
# 获取模板文件
template_file = f"{self.application.settings.get('template_path')}/{template_file}"
# 用参数感知模板加载器,加载模板文件,并传入 namespace 以便在加载完成后,执行数据准备
loader = ParamAwareLoader(os.path.dirname(template_file), namespace=namespace)
# 从文件中加载模板,同步完成数据准备
template = await loader.load_with_prepare(os.path.basename(template_file))
# 渲染模板,传入需要的数据
output = template.generate(**namespace)
return output
def response_ok(self, **kwargs):
self.log_request_end()
super().response_ok(**kwargs)
def response_error(self, e: Exception, status_code: int = 200, api_status_code: int = None, **kwargs):
self.log_request_end()
if api_status_code is None:
api_status_code = status_code
self.set_status(status_code=status_code)
chunk = {'code': api_status_code, 'status': 'error'}
chunk.update(kwargs)
if len(e.args) > 0 and isinstance(e.args[0], str):
chunk['msg'] = e.args[0]
if len(e.args) > 1:
if isinstance(e.args[1], dict):
chunk.update(e.args[1])
elif isinstance(e.args[1], list):
chunk['errors'] = e.args[1]
self.write(json.dumps(chunk, cls=JsonDumpsEncoder, ensure_ascii=False))
self.set_header('Content-Type', 'application/json')
def get_request_params(self):
"""
读取命令名称及请求参数。注意,参数命名应当避开 cmd 和 params。
该方法自动合并参数,并输出请求开始日志。
支持通过 Form 或 Json 两种方式提交请求并读取相应参数。
如使用 Form 方式,则应当在 form-data 中包含名为 cmd 的输入项,其值为对应的命令,其他输入项为命令参数。
注意:不会自动读取上传的文件数据,可通过::
self.request.files
方法读取上传的文件。
如使用 Json 方式,则应当遵循以下结构::
{
cmd: command_name,
params:
{
key: value
}
}
:return: 命令,命令对应的参数
"""
_arguments = self.request_arguments()
_cmd = _arguments.get('cmd', None)
_params = _arguments.get('params', None)
if _params is None:
_arguments.pop('cmd', None)
_params = _arguments
self.command = _cmd
self.request_params = _params
# 合成规则参数到参数字典,规则参数可在相应规则中修改
self.request_params.update(self.rule_kwargs)
# 取得命令和参数之后,记录请求开始日志
self.log_request_start()
return self.command, self.request_params
def log_request_end(self):
end_at = datetime.datetime.now()
total_delta = (end_at - self.start_at).total_seconds()
_spend = f"耗时:{total_delta:f} 秒."
_user_name = self.user.username if self.user else 'Unknown'
_log = f"O 用户:{_user_name} 完成 {self.request.uri}"
_log = f"{_log} 接口命令 {self.command}{_spend}" if self.command else f"{_log} 请求,{_spend}"
self.log(_log)
def log_request_start(self):
"""
收到请求时记录的日志
"""
_user_name = self.user.username if self.user else 'Unknown'
_log = f"I 用户:{_user_name} 请求 {self.request.uri}"
_log = f"{_log} 接口命令 {self.command}." if self.command else f"{_log}."
self.log(_log)