Files
DjangoAdmin_FastAPI_EleVue/core/app.py
T
ClaudeandClaude db4ee85db5 feat(phase1): core/ 基础设施迁移,旧路径改垫片
- core/: database/redis_client/jwt/password/response/exceptions/security/logger/deps/middleware/app
- create_app 迁移到 core/app.py,中间件注册顺序与异常处理器原样保留
- extensions/ utils/ apps/ 旧文件全部改为 re-export 垫片,import 路径保持兼容
- 新增 core 单元测试(jwt/password/response/request 共 12 个)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-07 10:02:01 +08:00

100 lines
3.6 KiB
Python

# +======================================================================
# | DjangoAdmin 企业数字化开发平台 [ 赋能开发者,助力企业发展 ]
# +----------------------------------------------------------------------
# | Copyright (c) 2021-2026 一米阳光团队 版权所有
# | 开源协议: Apache-2.0
# +======================================================================
# 由 apps/__init__.py 迁移而来。
"""应用工厂:create_app 组装中间件、路由、异常处理与 lifespan。"""
import time
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
from fastapi.logger import logger
from starlette.requests import Request
from starlette.responses import JSONResponse
from config.app import FASTAPI_DEBUG
from core.exceptions import AuthorizationException, BusinessException
from core.middleware import (
register_middleware,
register_cros,
db_session_middleware,
operation_log_middleware,
)
from core.redis_client import redis_lifespan, redis_middleware
from routers import register_router
def create_app() -> FastAPI:
app = FastAPI(
title="FastAPI",
description="FastAPI",
version="v1",
lifespan=redis_lifespan,
)
# 注册跨域中间件
register_cros(app)
# 注册Redis上下文注入中间件(先注册→内层:先注入Redis再开DB会话)
app.middleware("http")(redis_middleware)
# 注册数据库会话中间件(后注册→外层:DB会话包裹业务逻辑,finally保证关闭)
app.middleware("http")(db_session_middleware)
# 注册操作日志中间件(在DB会话内层,记录写操作日志)
app.middleware("http")(operation_log_middleware)
# 注册路由
register_router(app)
# 登录检测
register_middleware(app)
# 注册全局异常处理
register_exception(app)
# 请求计时(最后注册→最外层,统计完整耗时)
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(round(process_time, 5))
if FASTAPI_DEBUG:
logger.info(f"访问记录:{request.method} url:{request.url} 耗时:{str(round(process_time, 5))}")
return response
return app
# 注册全局异常处理
def register_exception(app: FastAPI):
"""全局异常捕获。"""
@app.exception_handler(AuthorizationException)
async def unicorn_exception_handler(request: Request, exc: AuthorizationException):
return JSONResponse(
status_code=200,
content={"code": exc.code, "data": None, "msg": exc.msg, "ok": False},
)
@app.exception_handler(BusinessException)
async def business_exception_handler(request: Request, exc: BusinessException):
return JSONResponse(
status_code=200,
content={"code": exc.code, "data": None, "msg": exc.msg, "ok": False},
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
errors = []
for err in exc.errors():
field = err.get("loc", [""])[-1]
msg = err.get("msg", "")
if field and field != "body":
errors.append(f"{field}: {msg}")
else:
errors.append(msg)
return JSONResponse(
status_code=200,
content={"code": 1, "data": None, "msg": "/".join(errors)},
)