feat: 初始化仓库
This commit is contained in:
7
config/__init__.py
Normal file
7
config/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# _*_ coding : UTF-8 _*_
|
||||
# @Time : 2025/01/17 21:13
|
||||
# @UpdateTime : 2025/01/17 21:13
|
||||
# @Author : sonder
|
||||
# @File : __init__.py.py
|
||||
# @Software : PyCharm
|
||||
# @Comment : 本程序
|
||||
265
config/constant.py
Normal file
265
config/constant.py
Normal file
@@ -0,0 +1,265 @@
|
||||
# _*_ coding : UTF-8 _*_
|
||||
# @Time : 2025/01/18 02:39
|
||||
# @UpdateTime : 2025/01/18 02:39
|
||||
# @Author : sonder
|
||||
# @File : constant.py
|
||||
# @Software : PyCharm
|
||||
# @Comment : 本程序
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class BusinessType(Enum):
|
||||
"""
|
||||
业务操作类型枚举
|
||||
定义系统中的操作类型,用于记录和分类业务日志。
|
||||
|
||||
枚举值说明:
|
||||
- OTHER: 其它操作,默认值为 0
|
||||
- SELECT: 查询操作,默认值为1
|
||||
- INSERT: 新增操作,值为 2
|
||||
- UPDATE: 修改操作,值为 3
|
||||
- DELETE: 删除操作,值为 4
|
||||
- GRANT: 授权操作,值为 5
|
||||
- EXPORT: 导出数据操作,值为 6
|
||||
- IMPORT: 导入数据操作,值为 7
|
||||
- FORCE: 强制退出操作,值为 8
|
||||
- GENCODE: 代码生成操作,值为 9
|
||||
- CLEAN: 清空数据操作,值为 10
|
||||
"""
|
||||
OTHER = 0
|
||||
"""
|
||||
其它操作,默认值为 0
|
||||
"""
|
||||
SELECT = 1
|
||||
"""
|
||||
查询操作,默认值为1
|
||||
"""
|
||||
INSERT = 2
|
||||
"""
|
||||
新增操作,值为 2
|
||||
"""
|
||||
UPDATE = 3
|
||||
"""
|
||||
修改操作,值为 3
|
||||
"""
|
||||
DELETE = 4
|
||||
"""
|
||||
删除操作,值为 4
|
||||
"""
|
||||
GRANT = 5
|
||||
"""
|
||||
授权操作,值为 5
|
||||
"""
|
||||
EXPORT = 6
|
||||
"""
|
||||
导出数据操作,值为 6
|
||||
"""
|
||||
IMPORT = 7
|
||||
"""
|
||||
导入数据操作,值为 7
|
||||
"""
|
||||
FORCE = 8
|
||||
"""
|
||||
强制退出操作,值为 8
|
||||
"""
|
||||
GENCODE = 9
|
||||
"""
|
||||
代码生成操作,值为 9
|
||||
"""
|
||||
CLEAN = 10
|
||||
"""
|
||||
清空数据操作,值为 10
|
||||
"""
|
||||
|
||||
|
||||
class CommonConstant:
|
||||
"""
|
||||
常用常量定义类,包含系统中常用的字符串标识和布尔值。
|
||||
|
||||
属性:
|
||||
WWW: `www.` 主域的前缀。
|
||||
HTTP: `http://` 协议前缀。
|
||||
HTTPS: `https://` 协议前缀。
|
||||
LOOKUP_RMI: RMI(远程方法调用)协议前缀。
|
||||
LOOKUP_LDAP: LDAP 协议前缀。
|
||||
LOOKUP_LDAPS: LDAPS 协议前缀。
|
||||
YES: 系统默认值 "是" 的标识。
|
||||
NO: 系统默认值 "否" 的标识。
|
||||
DEPT_NORMAL: 部门状态,表示正常。
|
||||
DEPT_DISABLE: 部门状态,表示停用。
|
||||
UNIQUE: 标识检查结果为唯一。
|
||||
NOT_UNIQUE: 标识检查结果为不唯一。
|
||||
"""
|
||||
|
||||
WWW = 'www.'
|
||||
"""`www.` 主域的前缀"""
|
||||
|
||||
HTTP = 'http://'
|
||||
"""`http://` 协议前缀"""
|
||||
|
||||
HTTPS = 'https://'
|
||||
"""`https://` 协议前缀"""
|
||||
|
||||
LOOKUP_RMI = 'rmi:'
|
||||
"""RMI(远程方法调用)协议前缀"""
|
||||
|
||||
LOOKUP_LDAP = 'ldap:'
|
||||
"""LDAP 协议前缀"""
|
||||
|
||||
LOOKUP_LDAPS = 'ldaps:'
|
||||
"""LDAPS 协议前缀"""
|
||||
|
||||
YES = 'Y'
|
||||
"""系统默认值 "是" 的标识"""
|
||||
|
||||
NO = 'N'
|
||||
"""系统默认值 "否" 的标识"""
|
||||
|
||||
DEPT_NORMAL = '0'
|
||||
"""部门状态,表示正常"""
|
||||
|
||||
DEPT_DISABLE = '1'
|
||||
"""部门状态,表示停用"""
|
||||
|
||||
UNIQUE = True
|
||||
"""标识检查结果为唯一"""
|
||||
|
||||
NOT_UNIQUE = False
|
||||
"""标识检查结果为不唯一"""
|
||||
|
||||
|
||||
class HttpStatusConstant:
|
||||
"""
|
||||
定义 HTTP 状态码的常量,描述不同操作的响应结果。
|
||||
|
||||
属性:
|
||||
SUCCESS: 表示操作成功,HTTP 状态码 200。
|
||||
CREATED: 表示资源已成功创建,HTTP 状态码 201。
|
||||
ACCEPTED: 表示请求已被接受,HTTP 状态码 202。
|
||||
NO_CONTENT: 表示操作成功但无内容返回,HTTP 状态码 204。
|
||||
MOVED_PERM: 表示资源已被永久移除,HTTP 状态码 301。
|
||||
SEE_OTHER: 表示重定向到其他资源,HTTP 状态码 303。
|
||||
NOT_MODIFIED: 表示资源未被修改,HTTP 状态码 304。
|
||||
BAD_REQUEST: 参数错误,HTTP 状态码 400。
|
||||
UNAUTHORIZED: 表示未授权,HTTP 状态码 401。
|
||||
FORBIDDEN: 表示禁止访问,HTTP 状态码 403。
|
||||
NOT_FOUND: 表示资源或服务未找到,HTTP 状态码 404。
|
||||
BAD_METHOD: 不允许的 HTTP 方法,HTTP 状态码 405。
|
||||
CONFLICT: 表示资源冲突,HTTP 状态码 409。
|
||||
UNSUPPORTED_TYPE: 不支持的数据或媒体类型,HTTP 状态码 415。
|
||||
ERROR: 表示系统内部错误,HTTP 状态码 500。
|
||||
NOT_IMPLEMENTED: 接口未实现,HTTP 状态码 501。
|
||||
WARN: 系统警告消息,自定义状态码 601。
|
||||
"""
|
||||
|
||||
SUCCESS = 200
|
||||
"""表示操作成功,HTTP 状态码 200。"""
|
||||
|
||||
CREATED = 201
|
||||
"""表示资源已成功创建,HTTP 状态码 201。"""
|
||||
|
||||
ACCEPTED = 202
|
||||
"""表示请求已被接受,HTTP 状态码 202。"""
|
||||
|
||||
NO_CONTENT = 204
|
||||
"""表示操作成功但无内容返回,HTTP 状态码 204。"""
|
||||
|
||||
MOVED_PERM = 301
|
||||
"""表示资源已被永久移除,HTTP 状态码 301。"""
|
||||
|
||||
SEE_OTHER = 303
|
||||
"""表示重定向到其他资源,HTTP 状态码 303。"""
|
||||
|
||||
NOT_MODIFIED = 304
|
||||
"""表示资源未被修改,HTTP 状态码 304。"""
|
||||
|
||||
BAD_REQUEST = 400
|
||||
"""参数错误,HTTP 状态码 400。"""
|
||||
|
||||
UNAUTHORIZED = 401
|
||||
"""表示未授权,HTTP 状态码 401。"""
|
||||
|
||||
FORBIDDEN = 403
|
||||
"""表示禁止访问,HTTP 状态码 403。"""
|
||||
|
||||
NOT_FOUND = 404
|
||||
"""表示资源或服务未找到,HTTP 状态码 404。"""
|
||||
|
||||
BAD_METHOD = 405
|
||||
"""不允许的 HTTP 方法,HTTP 状态码 405。"""
|
||||
|
||||
CONFLICT = 409
|
||||
"""表示资源冲突,HTTP 状态码 409。"""
|
||||
|
||||
UNSUPPORTED_TYPE = 415
|
||||
"""不支持的数据或媒体类型,HTTP 状态码 415。"""
|
||||
|
||||
ERROR = 500
|
||||
"""表示系统内部错误,HTTP 状态码 500。"""
|
||||
|
||||
NOT_IMPLEMENTED = 501
|
||||
"""接口未实现,HTTP 状态码 501。"""
|
||||
|
||||
WARN = 601
|
||||
"""系统警告消息,自定义状态码 601。"""
|
||||
|
||||
|
||||
class JobConstant:
|
||||
"""
|
||||
定时任务相关的常量,限制和规范任务模块的调用。
|
||||
|
||||
属性:
|
||||
JOB_ERROR_LIST: 禁止调用的模块及违规字符串列表,包含敏感或不安全操作。
|
||||
JOB_WHITE_LIST: 允许调用的模块列表,用于指定合法模块。
|
||||
"""
|
||||
|
||||
JOB_ERROR_LIST = [
|
||||
'app', 'config', 'exceptions', 'import ', 'middlewares',
|
||||
'module_admin', 'open(', 'os.', 'server', 'sub_applications',
|
||||
'subprocess.', 'sys.', 'utils', 'while ', '__import__', '"', "'",
|
||||
',', '?', ':', ';', '/', '|', '+', '-', '=', '~', '!', '#', '$',
|
||||
'%', '^', '&', '*', '<', '>', '(', ')', '[', ']', '{', '}', ' '
|
||||
]
|
||||
"""禁止调用的模块及违规字符串列表,包含敏感或不安全操作。"""
|
||||
|
||||
JOB_WHITE_LIST = ['module_task']
|
||||
"""允许调用的模块列表,用于指定合法模块。"""
|
||||
|
||||
|
||||
class RedisKeyConfig(Enum):
|
||||
"""
|
||||
定义 Redis 键的常量,用于缓存和存储数据。
|
||||
"""
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
"""
|
||||
获取 Redis 键名
|
||||
:return: 键名字符串
|
||||
"""
|
||||
return self.value.get('key')
|
||||
|
||||
@property
|
||||
def remark(self):
|
||||
"""
|
||||
获取键名备注信息
|
||||
:return: 备注信息字符串
|
||||
"""
|
||||
return self.value.get('remark')
|
||||
|
||||
ACCESS_TOKEN = {'key': 'access_token', 'remark': '登录令牌信息'}
|
||||
"""登录令牌信息,存储用户的访问令牌。"""
|
||||
USER_INFO = {'key': 'user_info', 'remark': '用户信息'}
|
||||
"""用户信息,存储用户的详细信息。"""
|
||||
USER_ROUTES = {'key': 'user_routes', 'remark': '用户路由信息'}
|
||||
"""用户路由信息,存储用户的路由信息。"""
|
||||
CAPTCHA_CODES = {'key': 'captcha_codes', 'remark': '图片验证码'}
|
||||
"""图片验证码,存储验证码及其校验信息。"""
|
||||
CAPTCHA_TYPES = {'key': 'captcha_types', 'remark': '图片验证码类型'}
|
||||
"""图片验证码类型,存储验证码类型及其配置信息。"""
|
||||
EMAIL_CODES = {'key': 'email_codes', 'remark': '邮箱验证码'}
|
||||
"""邮箱验证码,存储邮箱验证码及其校验信息。"""
|
||||
TRANSLATION_INFO = {'key': 'translation_info', 'remark': '国际化信息'}
|
||||
"""用于存储国际化数据。"""
|
||||
TRANSLATION_TYPES = {'key': 'translation_types', 'remark': '国际化类型'}
|
||||
"""国际化类型,存储国际化类型及其配置信息。"""
|
||||
138
config/database.py
Normal file
138
config/database.py
Normal file
@@ -0,0 +1,138 @@
|
||||
# _*_ coding : UTF-8 _*_
|
||||
# @Time : 2025/01/18 02:00
|
||||
# @UpdateTime : 2025/01/18 02:00
|
||||
# @Author : sonder
|
||||
# @File : database.py
|
||||
# @Software : PyCharm
|
||||
# @Comment : 本程序
|
||||
import logging
|
||||
import sys
|
||||
from logging.handlers import RotatingFileHandler
|
||||
|
||||
from tortoise import Tortoise
|
||||
|
||||
from config.env import DataBaseConfig
|
||||
from utils.log import logger, log_path_sql
|
||||
|
||||
|
||||
async def init_db():
|
||||
"""
|
||||
异步初始化数据库连接。
|
||||
"""
|
||||
# 在数据库连接 URL 中添加时区参数(东八区)
|
||||
db_url = (
|
||||
f"mysql://{DataBaseConfig.db_username}:{DataBaseConfig.db_password}@"
|
||||
f"{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}"
|
||||
"?charset=utf8mb4" # 指定时区为东八区,
|
||||
)
|
||||
|
||||
await Tortoise.init(
|
||||
db_url=db_url,
|
||||
modules={"models": ["models"]}, # 指向 models 目录,
|
||||
timezone="Asia/Shanghai",
|
||||
)
|
||||
|
||||
# 根据 db_echo 配置是否打印 SQL 查询日志
|
||||
if DataBaseConfig.db_echo:
|
||||
logger.info("SQL 查询日志已启用")
|
||||
await configure_tortoise_logging(enable_logging=True, log_level=DataBaseConfig.db_log_level)
|
||||
else:
|
||||
logger.info("SQL 查询日志已禁用")
|
||||
# 禁用 SQL 查询日志
|
||||
logger.remove(log_path_sql)
|
||||
|
||||
# 生成数据库表结构
|
||||
await Tortoise.generate_schemas()
|
||||
logger.success("数据库连接成功!")
|
||||
|
||||
|
||||
async def close_db():
|
||||
"""
|
||||
关闭数据库连接。
|
||||
"""
|
||||
await Tortoise.close_connections()
|
||||
logger.success("数据库连接关闭!")
|
||||
|
||||
|
||||
async def configure_tortoise_logging(enable_logging: bool = True, log_level: int = logging.DEBUG):
|
||||
"""
|
||||
异步配置 Tortoise ORM 日志输出。
|
||||
|
||||
:param enable_logging: 是否启用日志输出
|
||||
:param log_level: 日志输出级别,默认为 DEBUG
|
||||
"""
|
||||
aiomysql_logger = logging.getLogger("aiomysql")
|
||||
tortoise_logger = logging.getLogger("tortoise")
|
||||
|
||||
# 清除之前的处理器,避免重复添加
|
||||
if tortoise_logger.hasHandlers():
|
||||
tortoise_logger.handlers.clear()
|
||||
|
||||
if aiomysql_logger.hasHandlers():
|
||||
aiomysql_logger.handlers.clear()
|
||||
|
||||
if enable_logging:
|
||||
# 设置日志格式
|
||||
fmt = logging.Formatter(
|
||||
fmt="%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
|
||||
# 创建控制台处理器(输出到控制台)
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setLevel(log_level)
|
||||
console_handler.setFormatter(fmt)
|
||||
|
||||
# 创建文件处理器(输出到文件)
|
||||
file_handler = RotatingFileHandler(
|
||||
filename=log_path_sql,
|
||||
maxBytes=50 * 1024 * 1024, # 日志文件大小达到 50MB 时轮换
|
||||
backupCount=5, # 保留 5 个旧日志文件
|
||||
encoding="utf-8",
|
||||
)
|
||||
file_handler.setLevel(log_level)
|
||||
file_handler.setFormatter(fmt)
|
||||
|
||||
# 配置 tortoise 顶级日志记录器
|
||||
tortoise_logger.setLevel(log_level)
|
||||
tortoise_logger.addHandler(console_handler) # 添加控制台处理器
|
||||
tortoise_logger.addHandler(file_handler) # 添加文件处理器
|
||||
|
||||
# 配置 aiomysql 日志记录器
|
||||
aiomysql_logger.setLevel(log_level)
|
||||
aiomysql_logger.addHandler(console_handler) # 添加控制台处理器
|
||||
aiomysql_logger.addHandler(file_handler) # 添加文件处理器
|
||||
# 配置 SQL 查询日志记录器
|
||||
sql_logger = logging.getLogger("tortoise.db_client")
|
||||
sql_logger.setLevel(log_level)
|
||||
|
||||
class SQLResultLogger(logging.Handler):
|
||||
async def emit(self, record):
|
||||
# 只处理 SQL 查询相关的日志
|
||||
if "SELECT" in record.getMessage() or "INSERT" in record.getMessage() or "UPDATE" in record.getMessage() or "DELETE" in record.getMessage():
|
||||
# 输出 SQL 查询语句
|
||||
console_handler.emit(record)
|
||||
file_handler.emit(record)
|
||||
|
||||
# 异步获取并记录查询结果
|
||||
await self.log_query_result(record)
|
||||
|
||||
async def log_query_result(self, record):
|
||||
"""
|
||||
执行查询并返回结果。
|
||||
"""
|
||||
try:
|
||||
from tortoise import Tortoise
|
||||
connection = Tortoise.get_connection("default")
|
||||
result = await connection.execute_query_dict(record.getMessage())
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"获取查询结果失败: {str(e)}"
|
||||
|
||||
# 添加自定义 SQL 查询日志处理器
|
||||
sql_result_handler = SQLResultLogger()
|
||||
sql_result_handler.setLevel(log_level)
|
||||
sql_logger.addHandler(sql_result_handler)
|
||||
else:
|
||||
# 如果禁用日志,设置日志级别为 WARNING 以抑制大部分输出
|
||||
tortoise_logger.setLevel(logging.WARNING)
|
||||
539
config/env.py
Normal file
539
config/env.py
Normal file
@@ -0,0 +1,539 @@
|
||||
# _*_ coding : UTF-8 _*_
|
||||
# @Time : 2025/01/17 22:18
|
||||
# @UpdateTime : 2025/01/17 22:18
|
||||
# @Author : sonder
|
||||
# @File : env.py
|
||||
# @Software : PyCharm
|
||||
# @Comment : 本程序
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from functools import lru_cache
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
|
||||
class AppSettings(BaseSettings):
|
||||
"""
|
||||
应用配置类,用于管理 FastAPI 应用的基本设置。
|
||||
"""
|
||||
|
||||
app_env: str = 'dev'
|
||||
"""
|
||||
应用环境,默认为 'dev'。
|
||||
可选值:
|
||||
- 'dev': 开发环境
|
||||
- 'prod': 生产环境
|
||||
"""
|
||||
|
||||
app_name: str = 'FasAPI'
|
||||
"""
|
||||
应用名称,默认为 'FasAPI'。
|
||||
用于标识当前应用的名称。
|
||||
"""
|
||||
|
||||
app_root_path: str = '/dev-api'
|
||||
"""
|
||||
应用的根路径,默认为 '/dev-api'。
|
||||
用于设置 API 的根路径前缀。
|
||||
"""
|
||||
|
||||
app_host: str = '0.0.0.0'
|
||||
"""
|
||||
应用绑定的主机地址,默认为 '0.0.0.0'。
|
||||
- '0.0.0.0' 表示监听所有网络接口。
|
||||
- '127.0.0.1' 表示仅监听本地回环地址。
|
||||
"""
|
||||
|
||||
app_port: int = 9090
|
||||
"""
|
||||
应用绑定的端口号,默认为 9090。
|
||||
确保端口号未被其他服务占用。
|
||||
"""
|
||||
|
||||
app_version: str = '1.0.0'
|
||||
"""
|
||||
应用版本号,默认为 '1.0.0'。
|
||||
用于标识当前应用的版本。
|
||||
"""
|
||||
|
||||
app_reload: bool = True
|
||||
"""
|
||||
是否启用自动重载,默认为 True。
|
||||
- True: 启用自动重载,适合开发环境。
|
||||
- False: 禁用自动重载,适合生产环境。
|
||||
"""
|
||||
|
||||
app_ip_location_query: bool = True
|
||||
"""
|
||||
是否启用 IP 地址地理位置查询,默认为 True。
|
||||
- True: 启用 IP 地址地理位置查询功能。
|
||||
- False: 禁用 IP 地址地理位置查询功能。
|
||||
"""
|
||||
|
||||
app_same_time_login: bool = True
|
||||
"""
|
||||
是否允许同一用户同时登录多个设备,默认为 True。
|
||||
- True: 允许同一用户同时登录多个设备。
|
||||
- False: 禁止同一用户同时登录多个设备。
|
||||
"""
|
||||
|
||||
class Config:
|
||||
env_file_encoding = "utf-8" # 指定文件编码
|
||||
|
||||
|
||||
class JwtSettings(BaseSettings):
|
||||
"""
|
||||
JWT 配置类,用于管理 JWT(JSON Web Token)相关的设置。
|
||||
"""
|
||||
|
||||
jwt_secret_key: str = 'b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55'
|
||||
"""
|
||||
JWT 签名密钥,默认为一个随机生成的字符串。
|
||||
- 用于加密和解密 JWT 令牌。
|
||||
- 生产环境中应使用更安全的密钥,并妥善保管。
|
||||
"""
|
||||
|
||||
jwt_algorithm: str = 'HS256'
|
||||
"""
|
||||
JWT 签名算法,默认为 'HS256'。
|
||||
- 支持的算法包括:
|
||||
- 'HS256': HMAC + SHA-256
|
||||
- 'HS384': HMAC + SHA-384
|
||||
- 'HS512': HMAC + SHA-512
|
||||
- 'RS256': RSA + SHA-256
|
||||
- 其他算法请参考 PyJWT 文档。
|
||||
"""
|
||||
|
||||
jwt_salt: str = 'jwt_salt'
|
||||
"""
|
||||
JWT 盐值,默认为 'jwt_salt'。
|
||||
- 用于进一步增强 JWT 的安全性,防止彩虹表攻击。
|
||||
- 生产环境中应使用更复杂的盐值。
|
||||
"""
|
||||
|
||||
jwt_expire_minutes: int = 1440
|
||||
"""
|
||||
JWT 令牌的有效期(以分钟为单位),默认为 1440 分钟(24 小时)。
|
||||
- 超过有效期后,令牌将自动失效。
|
||||
- 可以根据需求调整有效期。
|
||||
"""
|
||||
|
||||
jwt_redis_expire_minutes: int = 30
|
||||
"""
|
||||
JWT 令牌在 Redis 中的缓存有效期(以分钟为单位),默认为 30 分钟。
|
||||
- 用于存储已签发的 JWT 令牌,以便快速验证和吊销。
|
||||
- 可以根据需求调整缓存有效期。
|
||||
"""
|
||||
|
||||
class Config:
|
||||
env_file_encoding = "utf-8" # 指定文件编码
|
||||
|
||||
|
||||
class DataBaseSettings(BaseSettings):
|
||||
"""
|
||||
数据库配置类,用于管理数据库连接相关的设置。
|
||||
"""
|
||||
|
||||
db_type: str = 'mysql'
|
||||
"""
|
||||
数据库类型,默认为 'mysql'。
|
||||
- 支持的数据库类型包括:
|
||||
- 'mysql': MySQL 数据库
|
||||
- 'postgresql': PostgreSQL 数据库
|
||||
- 'sqlite': SQLite 数据库
|
||||
"""
|
||||
|
||||
db_host: str = '127.0.0.1'
|
||||
"""
|
||||
数据库主机地址,默认为 '127.0.0.1'。
|
||||
- 如果数据库运行在本地,可以使用 'localhost' 或 '127.0.0.1'。
|
||||
- 如果数据库运行在远程服务器,请填写服务器的 IP 地址或域名。
|
||||
"""
|
||||
|
||||
db_port: int = 3306
|
||||
"""
|
||||
数据库端口号,默认为 3306。
|
||||
- MySQL 默认端口号为 3306。
|
||||
- PostgreSQL 默认端口号为 5432。
|
||||
- 根据实际数据库类型和配置调整端口号。
|
||||
"""
|
||||
|
||||
db_username: str = 'root'
|
||||
"""
|
||||
数据库用户名,默认为 'root'。
|
||||
- 用于连接数据库的用户名。
|
||||
- 生产环境中应使用具有最小权限的用户。
|
||||
"""
|
||||
|
||||
db_password: str = 'mysqlroot'
|
||||
"""
|
||||
数据库密码,默认为 'mysqlroot'。
|
||||
- 用于连接数据库的密码。
|
||||
- 生产环境中应使用强密码,并妥善保管。
|
||||
"""
|
||||
|
||||
db_database: str = 'fastapi'
|
||||
"""
|
||||
数据库名称,默认为 'fastapi'。
|
||||
- 用于指定连接的数据库名称。
|
||||
- 确保数据库已创建并具有相应的权限。
|
||||
"""
|
||||
|
||||
db_echo: bool = True
|
||||
"""
|
||||
是否打印 SQL 语句,默认为 True。
|
||||
- True: 打印所有执行的 SQL 语句,适合开发和调试。
|
||||
- False: 不打印 SQL 语句,适合生产环境。
|
||||
"""
|
||||
|
||||
db_max_overflow: int = 10
|
||||
"""
|
||||
连接池最大溢出连接数,默认为 10。
|
||||
- 当连接池中的连接数达到最大值时,允许额外创建的连接数。
|
||||
- 根据实际负载调整该值。
|
||||
"""
|
||||
|
||||
db_log_level: int = 10
|
||||
"""
|
||||
数据库日志级别,默认为 10(DEBUG)。
|
||||
- 用于控制数据库日志的输出级别。
|
||||
- 10: DEBUG
|
||||
- 20: INFO
|
||||
- 30: WARNING
|
||||
- 40: ERROR
|
||||
- 50: CRITICAL
|
||||
- 根据实际需求调整日志级别。
|
||||
"""
|
||||
|
||||
db_pool_size: int = 50
|
||||
"""
|
||||
连接池大小,默认为 50。
|
||||
- 连接池中保持的最大连接数。
|
||||
- 根据实际并发需求调整该值。
|
||||
"""
|
||||
|
||||
db_pool_recycle: int = 3600
|
||||
"""
|
||||
连接池回收时间(秒),默认为 3600 秒(1 小时)。
|
||||
- 超过该时间的连接会被回收并重新创建。
|
||||
- 用于避免数据库连接超时问题。
|
||||
"""
|
||||
|
||||
db_pool_timeout: int = 30
|
||||
"""
|
||||
连接池超时时间(秒),默认为 30 秒。
|
||||
- 从连接池获取连接的超时时间。
|
||||
- 如果超时未获取到连接,会抛出异常。
|
||||
"""
|
||||
|
||||
class Config:
|
||||
env_file_encoding = "utf-8" # 指定文件编码
|
||||
|
||||
|
||||
class RedisSettings(BaseSettings):
|
||||
"""
|
||||
Redis 配置类,用于管理 Redis 连接相关的设置。
|
||||
"""
|
||||
|
||||
redis_host: str = '127.0.0.1'
|
||||
"""
|
||||
Redis 主机地址,默认为 '127.0.0.1'。
|
||||
- 如果 Redis 运行在本地,可以使用 'localhost' 或 '127.0.0.1'。
|
||||
- 如果 Redis 运行在远程服务器,请填写服务器的 IP 地址或域名。
|
||||
"""
|
||||
|
||||
redis_port: int = 6379
|
||||
"""
|
||||
Redis 端口号,默认为 6379。
|
||||
- Redis 默认端口号为 6379。
|
||||
- 根据实际 Redis 配置调整端口号。
|
||||
"""
|
||||
|
||||
redis_username: str = ''
|
||||
"""
|
||||
Redis 用户名,默认为空。
|
||||
- 如果 Redis 启用了身份验证,请填写用户名。
|
||||
- 如果未启用身份验证,可以留空。
|
||||
"""
|
||||
|
||||
redis_password: str = ''
|
||||
"""
|
||||
Redis 密码,默认为空。
|
||||
- 如果 Redis 启用了身份验证,请填写密码。
|
||||
- 如果未启用身份验证,可以留空。
|
||||
"""
|
||||
|
||||
redis_database: int = 2
|
||||
"""
|
||||
Redis 数据库索引,默认为 2。
|
||||
- Redis 支持多个数据库,索引从 0 开始。
|
||||
- 根据实际需求选择合适的数据库索引。
|
||||
"""
|
||||
|
||||
class Config:
|
||||
env_file_encoding = "utf-8" # 指定文件编码
|
||||
|
||||
|
||||
class UploadSettings:
|
||||
"""
|
||||
上传配置类,用于管理文件上传和下载的相关设置。
|
||||
"""
|
||||
|
||||
UPLOAD_PREFIX = '/profile'
|
||||
"""
|
||||
文件上传的 URL 前缀,默认为 '/profile'。
|
||||
- 用于在访问上传文件时添加到 URL 的前缀。
|
||||
- 例如:`/profile/example.jpg`。
|
||||
"""
|
||||
|
||||
UPLOAD_PATH = 'data/upload_path'
|
||||
"""
|
||||
文件上传的存储路径,默认为 'data/upload_path'。
|
||||
- 上传的文件将存储在此目录中。
|
||||
- 如果目录不存在,会自动创建。
|
||||
"""
|
||||
|
||||
UPLOAD_MACHINE = 'A'
|
||||
"""
|
||||
上传机器的标识,默认为 'A'。
|
||||
- 用于区分不同的上传机器或节点。
|
||||
- 在多机部署时可以使用此字段。
|
||||
"""
|
||||
|
||||
DEFAULT_ALLOWED_EXTENSION = [
|
||||
# 图片
|
||||
'bmp',
|
||||
'gif',
|
||||
'jpg',
|
||||
'jpeg',
|
||||
'png',
|
||||
# word excel powerpoint
|
||||
'doc',
|
||||
'docx',
|
||||
'xls',
|
||||
'xlsx',
|
||||
'ppt',
|
||||
'pptx',
|
||||
'html',
|
||||
'htm',
|
||||
'txt',
|
||||
# 压缩文件
|
||||
'rar',
|
||||
'zip',
|
||||
'gz',
|
||||
'bz2',
|
||||
# 视频格式
|
||||
'mp4',
|
||||
'avi',
|
||||
'rmvb',
|
||||
# pdf
|
||||
'pdf',
|
||||
]
|
||||
"""
|
||||
默认允许上传的文件扩展名列表。
|
||||
- 包含常见的图片、文档、压缩文件、视频和 PDF 格式。
|
||||
- 可以根据需求扩展或修改此列表。
|
||||
"""
|
||||
|
||||
DOWNLOAD_PATH = 'data/download_path'
|
||||
"""
|
||||
文件下载的存储路径,默认为 'data/download_path'。
|
||||
- 下载的文件将存储在此目录中。
|
||||
- 如果目录不存在,会自动创建。
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
初始化方法,确保上传和下载路径存在。
|
||||
- 如果路径不存在,会自动创建。
|
||||
"""
|
||||
if not os.path.exists(self.UPLOAD_PATH):
|
||||
os.makedirs(self.UPLOAD_PATH)
|
||||
if not os.path.exists(self.DOWNLOAD_PATH):
|
||||
os.makedirs(self.DOWNLOAD_PATH)
|
||||
|
||||
|
||||
class EmailSettings(BaseSettings):
|
||||
"""
|
||||
邮件配置类,用于管理邮件发送相关的设置。
|
||||
"""
|
||||
email_username: str = ""
|
||||
"""
|
||||
邮件发送者的用户名,默认为空。
|
||||
"""
|
||||
email_password: str = ""
|
||||
"""
|
||||
邮件发送者的密码,默认为空。
|
||||
"""
|
||||
email_host: str = "smtp.qq.com"
|
||||
"""
|
||||
邮件服务器地址,默认为 "smtp.qq.com"。
|
||||
"""
|
||||
email_port: int = 465
|
||||
"""
|
||||
邮件服务器端口,默认为 465。
|
||||
"""
|
||||
|
||||
class Config:
|
||||
env_file_encoding = "utf-8" # 指定文件编码
|
||||
|
||||
|
||||
class MapSettings(BaseSettings):
|
||||
"""
|
||||
地图配置类,用于管理地图相关的设置。
|
||||
"""
|
||||
ak: str = ""
|
||||
"""
|
||||
控制台-应用管理-创建应用后获取的AK
|
||||
"""
|
||||
sk: str = ""
|
||||
"""
|
||||
控制台-应用管理-创建应用时,校验方式选择sn校验后生成的SK
|
||||
"""
|
||||
|
||||
|
||||
class CachePathConfig:
|
||||
"""
|
||||
缓存目录配置
|
||||
"""
|
||||
|
||||
PATH = os.path.join(os.path.abspath(os.getcwd()), 'caches')
|
||||
PATHSTR = 'caches'
|
||||
|
||||
|
||||
class GetConfig:
|
||||
"""
|
||||
获取配置类,用于集中管理和获取应用的所有配置。
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
初始化方法,解析命令行参数并加载环境变量。
|
||||
"""
|
||||
self.parse_cli_args()
|
||||
|
||||
@lru_cache()
|
||||
def get_app_config(self) -> BaseSettings:
|
||||
"""
|
||||
获取应用配置。
|
||||
- 返回 AppSettings 的实例。
|
||||
- 使用 lru_cache 缓存结果,避免重复实例化。
|
||||
"""
|
||||
# 实例化应用配置模型
|
||||
return AppSettings()
|
||||
|
||||
@lru_cache()
|
||||
def get_jwt_config(self) -> BaseSettings:
|
||||
"""
|
||||
获取 JWT 配置。
|
||||
- 返回 JwtSettings 的实例。
|
||||
- 使用 lru_cache 缓存结果,避免重复实例化。
|
||||
"""
|
||||
# 实例化 JWT 配置模型
|
||||
return JwtSettings()
|
||||
|
||||
@lru_cache()
|
||||
def get_database_config(self) -> BaseSettings:
|
||||
"""
|
||||
获取数据库配置。
|
||||
- 返回 DataBaseSettings 的实例。
|
||||
- 使用 lru_cache 缓存结果,避免重复实例化。
|
||||
"""
|
||||
# 实例化数据库配置模型
|
||||
return DataBaseSettings()
|
||||
|
||||
@lru_cache()
|
||||
def get_redis_config(self) -> BaseSettings:
|
||||
"""
|
||||
获取 Redis 配置。
|
||||
- 返回 RedisSettings 的实例。
|
||||
- 使用 lru_cache 缓存结果,避免重复实例化。
|
||||
"""
|
||||
# 实例化 Redis 配置模型
|
||||
return RedisSettings()
|
||||
|
||||
@lru_cache()
|
||||
def get_upload_config(self) -> 'UploadSettings':
|
||||
"""
|
||||
获取上传配置。
|
||||
- 返回 UploadSettings 的实例。
|
||||
- 使用 lru_cache 缓存结果,避免重复实例化。
|
||||
"""
|
||||
# 实例化上传配置
|
||||
return UploadSettings()
|
||||
|
||||
@lru_cache()
|
||||
def get_email_config(self) -> 'EmailSettings':
|
||||
"""
|
||||
获取邮件配置。
|
||||
- 返回 EmailSettings 的实例。
|
||||
- 使用 lru_cache 缓存结果,避免重复实例化。
|
||||
"""
|
||||
# 实例化邮件配置
|
||||
return EmailSettings()
|
||||
@lru_cache()
|
||||
def get_map_config(self) -> 'MapSettings':
|
||||
"""
|
||||
获取地图配置。
|
||||
- 返回 MapSettings 的实例。
|
||||
- 使用 lru_cache 缓存结果,避免重复实例化。
|
||||
"""
|
||||
# 实例化地图配置
|
||||
return MapSettings()
|
||||
|
||||
@staticmethod
|
||||
def parse_cli_args():
|
||||
"""
|
||||
解析命令行参数。
|
||||
- 如果使用 uvicorn 启动,命令行参数无法自定义。
|
||||
- 否则,使用 argparse 解析自定义命令行参数。
|
||||
- 根据命令行参数设置环境变量,并加载对应的 .env 文件。
|
||||
"""
|
||||
if 'uvicorn' in sys.argv[0]:
|
||||
# 使用 uvicorn 启动时,命令行参数需要按照 uvicorn 的文档进行配置,无法自定义参数
|
||||
pass
|
||||
else:
|
||||
# 使用 argparse 定义命令行参数
|
||||
parser = argparse.ArgumentParser(description='命令行参数')
|
||||
parser.add_argument('--env', type=str, default='', help='运行环境')
|
||||
# 解析命令行参数
|
||||
args = parser.parse_args()
|
||||
# 设置环境变量,如果未设置命令行参数,默认 APP_ENV 为 dev
|
||||
os.environ['APP_ENV'] = args.env if args.env else 'dev'
|
||||
|
||||
# 读取运行环境
|
||||
run_env = os.environ.get('APP_ENV', '')
|
||||
# 运行环境未指定时默认加载 .env.dev
|
||||
env_file = '.env.dev'
|
||||
# 运行环境不为空时按命令行参数加载对应 .env 文件
|
||||
if run_env != '':
|
||||
env_file = f'.env.{run_env}'
|
||||
# 加载配置
|
||||
load_dotenv(env_file)
|
||||
|
||||
|
||||
# 实例化获取配置类
|
||||
get_config = GetConfig()
|
||||
|
||||
# 应用配置
|
||||
AppConfig = get_config.get_app_config()
|
||||
|
||||
# JWT 配置
|
||||
JwtConfig = get_config.get_jwt_config()
|
||||
|
||||
# 数据库配置
|
||||
DataBaseConfig = get_config.get_database_config()
|
||||
|
||||
# Redis 配置
|
||||
RedisConfig = get_config.get_redis_config()
|
||||
|
||||
# 上传配置
|
||||
UploadConfig = get_config.get_upload_config()
|
||||
|
||||
# 邮件配置
|
||||
EmailConfig = get_config.get_email_config()
|
||||
|
||||
# 地图配置
|
||||
MapConfig = get_config.get_map_config()
|
||||
68
config/get_redis.py
Normal file
68
config/get_redis.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# _*_ coding : UTF-8 _*_
|
||||
# @Time : 2025/01/18 02:41
|
||||
# @UpdateTime : 2025/01/18 02:41
|
||||
# @Author : sonder
|
||||
# @File : get_redis.py
|
||||
# @Software : PyCharm
|
||||
# @Comment : 本程序
|
||||
|
||||
from redis import asyncio as aioredis
|
||||
from redis.exceptions import AuthenticationError, TimeoutError, RedisError
|
||||
|
||||
from config.env import RedisConfig
|
||||
from utils.log import logger
|
||||
|
||||
|
||||
class Redis:
|
||||
"""
|
||||
Redis工具类
|
||||
提供与 Redis 交互的常用方法,包括连接管理和缓存初始化。
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
async def create_redis_pool(cls) -> aioredis.Redis:
|
||||
"""
|
||||
应用启动时初始化 Redis 连接池。
|
||||
|
||||
该方法通过 `aioredis` 创建一个 Redis 连接池,并验证连接是否成功。
|
||||
如果连接失败,会捕获异常并记录错误日志。
|
||||
|
||||
:return: Redis 连接对象
|
||||
"""
|
||||
logger.info('开始连接 Redis...')
|
||||
redis = await aioredis.from_url(
|
||||
url=f'redis://{RedisConfig.redis_host}',
|
||||
port=RedisConfig.redis_port,
|
||||
username=RedisConfig.redis_username,
|
||||
password=RedisConfig.redis_password,
|
||||
db=RedisConfig.redis_database,
|
||||
encoding='utf-8', # 默认编码为 UTF-8
|
||||
decode_responses=True, # 自动解码 Redis 响应
|
||||
)
|
||||
try:
|
||||
# 测试 Redis 连接
|
||||
connection = await redis.ping()
|
||||
if connection:
|
||||
logger.info('Redis 连接成功')
|
||||
else:
|
||||
logger.error('Redis 连接失败')
|
||||
except AuthenticationError as e:
|
||||
logger.error(f'Redis 用户名或密码错误,详细错误信息:{e}')
|
||||
except TimeoutError as e:
|
||||
logger.error(f'Redis 连接超时,详细错误信息:{e}')
|
||||
except RedisError as e:
|
||||
logger.error(f'Redis 连接错误,详细错误信息:{e}')
|
||||
return redis
|
||||
|
||||
@classmethod
|
||||
async def close_redis_pool(cls, app):
|
||||
"""
|
||||
应用关闭时关闭 Redis 连接池。
|
||||
|
||||
在应用生命周期结束时,清理 Redis 连接池以释放资源。
|
||||
|
||||
:param app: FastAPI 应用对象,用于访问全局 Redis 连接池。
|
||||
:return: None
|
||||
"""
|
||||
await app.state.redis.close()
|
||||
logger.info('关闭 Redis 连接成功')
|
||||
Reference in New Issue
Block a user