mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-21 04:46:26 +00:00
- Added *.pyc and *.pyo to .gitignore to prevent compiled Python files from being tracked. - Improved docstrings in various modules, providing clearer descriptions of functions, parameters, and return values to enhance code readability and maintainability.
326 lines
13 KiB
Python
Executable File
326 lines
13 KiB
Python
Executable File
import os
|
|
from functools import lru_cache
|
|
from pathlib import Path
|
|
from typing import Any, Literal
|
|
from urllib.parse import quote_plus
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
from app.common.enums import EnvironmentEnum
|
|
from app.config.path_conf import BASE_DIR, ENV_DIR
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""系统配置类"""
|
|
|
|
model_config = SettingsConfigDict(
|
|
env_file=ENV_DIR / f".env.{os.getenv('ENVIRONMENT')}",
|
|
env_file_encoding="utf-8",
|
|
extra="ignore",
|
|
case_sensitive=True, # 区分大小写
|
|
)
|
|
|
|
# ================================================= #
|
|
# ******************* 项目环境 ****************** #
|
|
# ================================================= #
|
|
ENVIRONMENT: EnvironmentEnum = EnvironmentEnum.DEV
|
|
|
|
# ================================================= #
|
|
# ******************* 服务器配置 ****************** #
|
|
# ================================================= #
|
|
SERVER_HOST: str = "0.0.0.0" # 允许访问的IP地址
|
|
SERVER_PORT: int = 8001 # 服务端口
|
|
|
|
# ================================================= #
|
|
# ******************* API文档配置 ****************** #
|
|
# ================================================= #
|
|
DEBUG: bool = True # 调试模式
|
|
TITLE: str = "🎉 FastapiAdmin 🎉 " # 文档标题
|
|
VERSION: str = "0.1.0" # 版本号
|
|
DESCRIPTION: str = (
|
|
"该项目是一个基于python的web服务框架,基于fastapi和sqlalchemy实现。" # 文档描述
|
|
)
|
|
SUMMARY: str = "接口汇总" # 文档概述
|
|
DOCS_URL: str = "/docs" # Swagger UI路径
|
|
REDOC_URL: str = "/redoc" # ReDoc路径
|
|
LJDOC_URL: str = "/ljdoc" # LangJin UI路径
|
|
ROOT_PATH: str = "/api/v1" # API路由前缀
|
|
|
|
# ================================================= #
|
|
# ******************** 日志配置 ******************** #
|
|
# ================================================= #
|
|
LOGGER_LEVEL: str = "DEBUG" # 日志级别
|
|
|
|
# ================================================= #
|
|
# ******************** 跨域配置 ******************** #
|
|
# ================================================= #
|
|
CORS_ORIGIN_ENABLE: bool = True # 是否启用跨域
|
|
ALLOW_ORIGINS: list[str] = ["*"] # 允许的域名列表
|
|
ALLOW_METHODS: list[str] = ["*"] # 允许的HTTP方法
|
|
ALLOW_HEADERS: list[str] = ["*"] # 允许的请求头
|
|
ALLOW_CREDENTIALS: bool = True # 是否允许携带cookie
|
|
CORS_EXPOSE_HEADERS: list[str] = ["X-Request-ID"]
|
|
|
|
# ================================================= #
|
|
# ******************* 登录认证配置 ****************** #
|
|
# ================================================= #
|
|
SECRET_KEY: str = "vgb0tnl9d58+6n-6h-ea&u^1#s0ccp!794=krylxcjq75vzps$" # JWT密钥
|
|
ALGORITHM: str = "HS256" # JWT算法
|
|
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 30 # access_token过期时间(秒)30 分钟
|
|
REFRESH_TOKEN_EXPIRE_MINUTES: int = 60 * 30 # refresh_token过期时间(秒)30 分钟
|
|
TOKEN_TYPE: str = "bearer" # token类型
|
|
TOKEN_REQUEST_PATH_EXCLUDE: list[str] = ["api/v1/auth/login"] # JWT / RBAC 路由白名单
|
|
TOKEN_SLIDING_EXPIRE: bool = True # 是否启用滑动过期(用户操作时自动续期)
|
|
|
|
# ================================================= #
|
|
# ******************** 数据库配置 ******************* #
|
|
# ================================================= #
|
|
SQL_DB_ENABLE: bool = True # 是否启用数据库
|
|
DATABASE_ECHO: bool | Literal["debug"] = False # 是否显示SQL日志
|
|
ECHO_POOL: bool | Literal["debug"] = False # 是否显示连接池日志
|
|
POOL_SIZE: int = 10 # 连接池大小
|
|
MAX_OVERFLOW: int = 20 # 最大溢出连接数
|
|
POOL_TIMEOUT: int = 30 # 连接超时时间(秒)
|
|
POOL_RECYCLE: int = 1800 # 连接回收时间(秒)
|
|
POOL_USE_LIFO: bool = True # 是否使用LIFO连接池
|
|
POOL_PRE_PING: bool = True # 是否开启连接预检
|
|
FUTURE: bool = True # 是否使用SQLAlchemy 2.0特性
|
|
AUTOCOMMIT: bool = False # 是否自动提交
|
|
AUTOFETCH: bool = False # 是否自动刷新
|
|
EXPIRE_ON_COMMIT: bool = False # 是否在提交时过期
|
|
|
|
# MySQL/PostgreSQL数据库连接
|
|
DATABASE_TYPE: Literal["mysql", "postgres", "sqlite"] = "mysql"
|
|
DATABASE_HOST: str = "localhost"
|
|
DATABASE_PORT: int = 3306
|
|
DATABASE_USER: str = "root"
|
|
DATABASE_PASSWORD: str = "ServBay.dev"
|
|
DATABASE_NAME: str = "fastapiadmin"
|
|
|
|
# ================================================= #
|
|
# ******************** Redis配置 ******************* #
|
|
# ================================================= #
|
|
REDIS_ENABLE: bool = True # 是否启用Redis
|
|
REDIS_HOST: str = "localhost"
|
|
REDIS_PORT: int = 6379
|
|
REDIS_DB_NAME: int = 1
|
|
REDIS_USER: str = ""
|
|
REDIS_PASSWORD: str = ""
|
|
|
|
# ================================================= #
|
|
# ******************** 验证码配置 ******************* #
|
|
# ================================================= #
|
|
CAPTCHA_ENABLE: bool = True # 是否启用验证码
|
|
CAPTCHA_EXPIRE_SECONDS: int = 60 * 1 # 验证码过期时间(秒) 1分钟
|
|
CAPTCHA_FONT_SIZE: int = 35 # 字体大小
|
|
CAPTCHA_FONT_PATH: str = "static/assets/font/Arial.ttf" # 字体路径
|
|
|
|
# 是否请求外网解析 IP 归属地(登录发 token、操作日志写 login_location 共用;关闭可明显加快登录)
|
|
LOGIN_RESOLVE_IP_LOCATION: bool = False
|
|
|
|
# ================================================= #
|
|
# ********************* 日志配置 ******************* #
|
|
# ================================================= #
|
|
OPERATION_LOG_RECORD: bool = True # 是否记录操作日志
|
|
IGNORE_OPERATION_FUNCTION: list[str] = ["get_captcha_for_login"] # 忽略记录的函数
|
|
OPERATION_RECORD_METHOD: list[str] = [
|
|
"POST",
|
|
"PUT",
|
|
"PATCH",
|
|
"DELETE",
|
|
"HEAD",
|
|
"OPTIONS",
|
|
] # 需要记录的请求方法
|
|
|
|
# ================================================= #
|
|
# ******************* Gzip压缩配置 ******************* #
|
|
# ================================================= #
|
|
GZIP_ENABLE: bool = True # 是否启用Gzip
|
|
GZIP_MIN_SIZE: int = 1000 # 最小压缩大小(字节)
|
|
GZIP_COMPRESS_LEVEL: int = 9 # 压缩级别(1-9)
|
|
|
|
# ================================================= #
|
|
# ***************** 静态文件配置 ***************** #
|
|
# ================================================= #
|
|
STATIC_ENABLE: bool = True # 是否启用静态文件
|
|
STATIC_URL: str = "/static" # 访问路由
|
|
STATIC_DIR: str = "static" # 目录名
|
|
STATIC_ROOT: Path = BASE_DIR.joinpath(STATIC_DIR) # 绝对路径
|
|
|
|
# ================================================= #
|
|
# ***************** 动态文件配置 ***************** #
|
|
# ================================================= #
|
|
UPLOAD_FILE_PATH: Path = Path("static/upload") # 上传目录
|
|
UPLOAD_MACHINE: str = "A" # 上传机器标识
|
|
ALLOWED_EXTENSIONS: list[str] = [ # 允许的文件类型
|
|
".gif",
|
|
".jpg",
|
|
".jpeg",
|
|
".png",
|
|
".ico",
|
|
".svg",
|
|
".xls",
|
|
".xlsx",
|
|
]
|
|
MAX_FILE_SIZE: int = 10 * 1024 * 1024 # 最大文件大小(10MB)
|
|
|
|
# ================================================= #
|
|
# ***************** Swagger配置 ***************** #
|
|
# ================================================= #
|
|
SWAGGER_CSS_URL: str = "static/swagger/swagger-ui/swagger-ui.css"
|
|
SWAGGER_JS_URL: str = "static/swagger/swagger-ui/swagger-ui-bundle.js"
|
|
REDOC_JS_URL: str = "static/swagger/redoc/bundles/redoc.standalone.js"
|
|
CUSTOM_CSS_URL: str = "static/swagger/custom-ui/styles.css"
|
|
CUSTOM_JS_URL: str = "static/swagger/custom-ui/scripts.js"
|
|
FAVICON_URL: str = "static/swagger/favicon.png"
|
|
|
|
# ================================================= #
|
|
# ******************* AI大模型配置 ****************** #
|
|
# ================================================= #
|
|
OPENAI_BASE_URL: str = ""
|
|
OPENAI_API_KEY: str = ""
|
|
OPENAI_MODEL: str = ""
|
|
|
|
# ================================================= #
|
|
# ******************* ChromaDB配置 ****************** #
|
|
# ================================================= #
|
|
CHROMA_PERSIST_DIR: str = str(BASE_DIR / "data" / "chroma") # ChromaDB 持久化目录
|
|
CHROMA_COLLECTION_NAME: str = "knowledge_base" # ChromaDB 集合名称
|
|
|
|
# ================================================= #
|
|
# ******************* 请求限制配置 ****************** #
|
|
# ================================================= #
|
|
REQUEST_LIMITER_REDIS_PREFIX: str = "fastapiadmin:request_limiter:"
|
|
|
|
# ================================================= #
|
|
# ******************* 重构配置 ******************* #
|
|
# ================================================= #
|
|
@property
|
|
def MIDDLEWARE_LIST(self) -> list[str | None]:
|
|
"""
|
|
根据开关组装的中间件类路径列表(未启用的项为 None)。
|
|
|
|
返回:
|
|
- list[str | None]: 中间件 import 路径或 None。
|
|
"""
|
|
# 中间件列表
|
|
MIDDLEWARES: list[str | None] = [
|
|
"app.core.middlewares.CustomCORSMiddleware" if self.CORS_ORIGIN_ENABLE else None,
|
|
"app.core.middlewares.RequestLogMiddleware" if self.OPERATION_LOG_RECORD else None,
|
|
"app.core.middlewares.CustomGZipMiddleware" if self.GZIP_ENABLE else None,
|
|
]
|
|
return MIDDLEWARES
|
|
|
|
@property
|
|
def EVENT_LIST(self) -> list[str | None]:
|
|
"""
|
|
应用启动时加载的全局异步事件模块路径列表。
|
|
|
|
返回:
|
|
- list[str | None]: 事件模块路径或 None。
|
|
"""
|
|
EVENTS: list[str | None] = [
|
|
"app.core.database.redis_connect" if self.REDIS_ENABLE else None,
|
|
]
|
|
return EVENTS
|
|
|
|
@property
|
|
def ASYNC_DB_URI(self) -> str:
|
|
"""
|
|
异步 SQLAlchemy 数据库 URL。
|
|
|
|
返回:
|
|
- str: 异步驱动连接串。
|
|
|
|
异常:
|
|
- ValueError: 数据库类型不支持时抛出。
|
|
"""
|
|
if self.DATABASE_TYPE not in ("mysql", "postgres", "sqlite"):
|
|
raise ValueError(
|
|
f"数据库驱动不支持: {self.DATABASE_TYPE}, 异步数据库请选择 mysql、postgres、sqlite"
|
|
)
|
|
db_connect: str = ""
|
|
if self.DATABASE_TYPE == "mysql":
|
|
db_connect = f"mysql+asyncmy://{self.DATABASE_USER}:{quote_plus(self.DATABASE_PASSWORD)}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}?charset=utf8mb4"
|
|
elif self.DATABASE_TYPE == "postgres":
|
|
db_connect = f"postgresql+asyncpg://{self.DATABASE_USER}:{quote_plus(self.DATABASE_PASSWORD)}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}"
|
|
else:
|
|
db_connect = f"sqlite+aiosqlite:///{self.DATABASE_NAME}.db"
|
|
return db_connect
|
|
|
|
@property
|
|
def DB_URI(self) -> str:
|
|
"""
|
|
同步 SQLAlchemy 数据库 URL。
|
|
|
|
返回:
|
|
- str: 同步驱动连接串。
|
|
|
|
异常:
|
|
- ValueError: 数据库类型不支持时抛出。
|
|
"""
|
|
if self.DATABASE_TYPE not in ("mysql", "postgres", "sqlite"):
|
|
raise ValueError(
|
|
f"数据库驱动不支持: {self.DATABASE_TYPE}, 同步数据库请选择 mysql、postgres、sqlite"
|
|
)
|
|
db_connect: str = ""
|
|
if self.DATABASE_TYPE == "mysql":
|
|
db_connect = f"mysql+pymysql://{self.DATABASE_USER}:{quote_plus(self.DATABASE_PASSWORD)}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}?charset=utf8mb4"
|
|
elif self.DATABASE_TYPE == "postgres":
|
|
db_connect = f"postgresql+psycopg://{self.DATABASE_USER}:{quote_plus(self.DATABASE_PASSWORD)}@{self.DATABASE_HOST}:{self.DATABASE_PORT}/{self.DATABASE_NAME}"
|
|
else:
|
|
db_connect = f"sqlite:///{self.DATABASE_NAME}.db"
|
|
return db_connect
|
|
|
|
@property
|
|
def REDIS_URI(self) -> str:
|
|
"""
|
|
Redis 连接 URL。
|
|
|
|
返回:
|
|
- str: redis:// 连接串。
|
|
"""
|
|
return f"redis://{self.REDIS_USER}:{self.REDIS_PASSWORD}@{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB_NAME}"
|
|
|
|
@property
|
|
def FASTAPI_CONFIG(self) -> dict[str, Any]:
|
|
"""
|
|
创建 FastAPI 应用实例时使用的关键字参数子集。
|
|
|
|
返回:
|
|
- dict[str, Any]: debug、title、responses 等配置。
|
|
"""
|
|
return {
|
|
"debug": self.DEBUG,
|
|
"title": self.TITLE,
|
|
"version": self.VERSION,
|
|
"description": self.DESCRIPTION,
|
|
"summary": self.SUMMARY,
|
|
"docs_url": None,
|
|
"redoc_url": None,
|
|
"root_path": self.ROOT_PATH,
|
|
"responses": {
|
|
200: {"description": "成功"},
|
|
400: {"description": "请求参数错误"},
|
|
401: {"description": "未认证"},
|
|
403: {"description": "未授权"},
|
|
404: {"description": "资源不存在"},
|
|
422: {"description": "请求参数验证错误"},
|
|
500: {"description": "服务器内部错误"},
|
|
},
|
|
}
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def get_settings() -> Settings:
|
|
"""
|
|
获取全局 Settings 单例(lru_cache 缓存)。
|
|
|
|
返回:
|
|
- Settings: 配置实例。
|
|
"""
|
|
return Settings()
|
|
|
|
|
|
settings = get_settings()
|