项目框架的搭建
1.项目结构规划1.1主文件main.py 是FastAPI应用主入口from contextlib import asynccontextmanager from fastapi import FastAPI from starlette.middleware.cors import CORSMiddleware from starlette.middleware.trustedhost import TrustedHostMiddleware from tortoise import Tortoise from app.config.settings import settings from app.core.database import TORTOISE_ORM from app.core.exception_handler import global_exception_handler from app.core.logging import logger from app.core.middlewares import LoggingMiddleware # https://fastapi.tiangolo.com/advanced/events/#async-context-manager asynccontextmanager async def lifespan(app: FastAPI): logger.info(正要启动数据库连接) # Tortoise 1.1 uses TortoiseContext (contextvars). Lifespan and request # handlers run in different tasks, so enable global fallback for FastAPI. await Tortoise.init(configTORTOISE_ORM, _enable_global_fallbackTrue) logger.debug(数据库连接启动成功) yield await Tortoise.close_connections() logger.error(数据库连接已关闭) app FastAPI( titlesettings.app_title, versionsettings.app_version, descriptionsettings.app_description, lifespanlifespan ) # 允许跨域 app.add_middleware(CORSMiddleware, allow_origins[*], allow_methods[*], allow_headers[*], allow_credentialsTrue) # 允许 Host访问 app.add_middleware(TrustedHostMiddleware, allowed_hosts[*]) app.add_middleware(LoggingMiddleware) # 全局异常处理 app.add_exception_handler( Exception, global_exception_handler )1.2requirements.txt 存放Python依赖包执行收集所有包pip freeze requirements.txt执行下载文件中所有依赖pip install -r requirements.txt1.3 app 应用核心代码1models # 数据模型层 (Tortoise ORM) 创建表 # 用户相关模型(2) apis # API路由层[接受参数,返回数据] # 用户相关API(3) schems # 数据验证层 (Pydantic) # 用户请求/响应模型(4) services # 业务服务层 (逻辑) # 用户相关的业务代码/方法(5) core # 核心文件(5.1) database.py # 数据库连接信息# app/core/database.py 数据库配置文件 这个文件定义了 Tortoise-ORM 连接 MySQL 数据库所需的所有配置信息 from app.config.settings import settings # TORTOISE_ORM 是 Tortoise-ORM 规定的配置字典变量名 # 后面用 register_tortoise 或 Aerich 时都会引用这个字典 TORTOISE_ORM { # 1. 连接配置 —— 定义数据库连接信息 connections: { # default 是默认连接的名字必须有一个 default default: { # engine指定数据库后端引擎MySQL 使用 tortoise.backends.mysql engine: tortoise.backends.mysql, # credentials数据库连接凭证包含主机、端口、用户名、密码等 credentials: { host: settings.db_host, # MySQL 服务器地址 port: settings.db_port, # MySQL 端口默认 3306 user: settings.db_user, # 数据库用户名 password: settings.db_password, # 数据库密码请根据实际情况修改 database: settings.db_name, # 数据库名称 minsize: settings.db_minsize, # 连接池最小连接数 maxsize: settings.db_maxsize, # 连接池最大连接数 charset: utf8mb4, # 字符集支持 emoji echo: settings.db_echo # 是否打印 SQL 语句开发环境建议开启 } } }, # 2. 应用配置 —— 指定模型所在的模块 apps: { # models 是应用的名字可以自定义但 Aerich 需要使用这个名字 models: { # models 列表指定包含 Tortoise 模型类的 Python 模块路径 # aerich.models 是 Aerich 的内置模型用于记录迁移历史必须包含 models: [app.models, aerich.models], # default_connection指定这个应用使用哪个数据库连接 default_connection: default, } }, # 3. 时区配置 use_tz: False, # 是否使用时区 timezone: Asia/Shanghai, # 时区设置 echo: True # ✅ 关键打开 SQL 打印 }(5.2) logging.py # 日志依赖包pip install logurushell # app/core/logging.py from loguru import logger import sys import logging from pathlib import Path from app.config.settings import settings # 移除默认处理器 logger.remove() # 控制台输出开发环境 logger.add( sys.stdout, formatgreen{time:YYYY-MM-DD HH:mm:ss}/green | level{level: 8}/level | cyan{name}/cyan:cyan{function}/cyan:cyan{line}/cyan - level{message}/level, levelDEBUG if settings.DEBUG else INFO, colorizeTrue ) # 创建日志目录 log_dir Path(logs) log_dir.mkdir(exist_okTrue) # INFO 级别及以上日志文件 logger.add( log_dir / info_{time:YYYY-MM-DD}.log, rotation00:00, # 每天午夜轮转 retention30 days, # 保留 30 天 compressionzip, # 压缩旧日志 levelINFO, format{time:YYYY-MM-DD HH:mm:ss} | {level: 8} | {name}:{function}:{line} - {message}, encodingutf-8, filterlambda record: record[level].name INFO ) # WARNING 级别日志文件 logger.add( log_dir / warning_{time:YYYY-MM-DD}.log, rotation00:00, # 每天午夜轮转 retention30 days, # 保留 30 天 compressionzip, # 压缩旧日志 levelWARNING, format{time:YYYY-MM-DD HH:mm:ss} | {level: 8} | {name}:{function}:{line} - {message}, encodingutf-8, filterlambda record: record[level].name WARNING ) # ERROR 级别及以上日志文件 logger.add( log_dir / error_{time:YYYY-MM-DD}.log, rotation00:00, # 每天午夜轮转 retention90 days, # 保留 90 天错误日志保留更长时间 compressionzip, # 压缩旧日志 levelERROR, format{time:YYYY-MM-DD HH:mm:ss} | {level: 8} | {name}:{function}:{line} - {message}, encodingutf-8, filterlambda record: record[level].name in [ERROR, CRITICAL] ) # 全量日志文件包含所有级别 logger.add( log_dir / all_{time:YYYY-MM-DD}.log, rotation00:00, # 每天午夜轮转 retention7 days, # 保留 7 天 compressionzip, # 压缩旧日志 levelDEBUG, format{time:YYYY-MM-DD HH:mm:ss} | {level: 8} | {name}:{function}:{line} - {message}, encodingutf-8 ) # SQL 日志文件专门记录数据库 SQL 语句 def sql_filter(record): 过滤 SQL 相关的日志 name record[name].lower() message record[message].lower() # 捕获 tortoise 后端相关的日志特别是包含 SQL 语句的日志 return ( tortoise.backends in name or sql in message or select in message or insert in message or update in message or delete in message or create in message or alter in message ) logger.add( log_dir / sql_{time:YYYY-MM-DD}.log, rotation00:00, # 每天午夜轮转 retention30 days, # 保留 30 天 compressionzip, # 压缩旧日志 levelDEBUG, format{time:YYYY-MM-DD HH:mm:ss} | {level: 8} | {name} - {message}, encodingutf-8, filtersql_filter ) # 配置标准 logging 模块将 Tortoise ORM 的日志转发到 loguru class InterceptHandler(logging.Handler): 拦截标准 logging 的输出转发到 loguru def emit(self, record): # 获取对应的 loguru 级别 try: level logger.level(record.levelname).name except ValueError: level record.levelno # 找到调用者信息 frame, depth sys._getframe(6), 6 while frame and frame.f_code.co_filename logging.__file__: frame frame.f_back depth 1 logger.opt(depthdepth, exceptionrecord.exc_info).log(level, record.getMessage()) # 配置 Tortoise ORM 的 logger def setup_tortoise_logging(): 配置 Tortoise ORM 的日志输出 # 拦截所有 tortoise 相关的 logger logging_loggers [ asyncmy, tortoise, tortoise.backends, tortoise.backends.mysql, tortoise.backends.asyncpg, tortoise.backends.sqlite, ] for logger_name in logging_loggers: logging_logger logging.getLogger(logger_name) logging_logger.handlers [InterceptHandler()] logging_logger.setLevel(logging.DEBUG if settings.db_echo else logging.INFO) logging_logger.propagate False # 初始化 Tortoise 日志配置 if settings.db_echo: setup_tortoise_logging() # 导出 logger __all__ [logger, setup_tortoise_logging] (5.3) exception_handler.py # 全局异常处理 全局异常处理 from starlette.requests import Request from starlette.responses import JSONResponse from app.core.logging import logger def global_exception_handler(request: Request, exc: Exception) - JSONResponse: logger.error(出现了Exception异常) return JSONResponse( status_code500, content{ code: 0, message: str(exc) } )(5.4) middlewares.py # 中间件from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint from starlette.requests import Request from starlette.responses import Response from app.core.logging import logger class LoggingMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) - Response: method request.method qp request.query_params url request.url logger.info(f{method} {url} {qp}) response await call_next(request) return response(6) config # 配置文件(6.1) settings.py # 多环境配置import os from typing import Optional from pydantic_settings import BaseSettings, SettingsConfigDict class BaseAppSettings(BaseSettings): 基础配置类所有环境共享 model_config SettingsConfigDict( env_file_encodingutf-8, case_sensitiveFalse, extraignore, # 让子类继承 env 配置不会被覆盖掉这是核心修复 env_file.env, ) # 通用配置 app_title: str BOSS服务端项目 app_version: str V1.0.0 api_prefix: str /api/v1 app_description: str Boss项目的接口文档,包含求职者端,企业端,管理端 class DevAppSettings(BaseAppSettings): 开发环境 model_config SettingsConfigDict(env_file.env.dev) # 服务 server_port: int 8000 debug_mode: bool True # 数据库 db_url: str mysqlpymysql://root:123456localhost:3306/fastApiProject004 db_host: str localhost db_port: int 3306 db_user: str root db_password: str root db_name: str boss_api db_echo: bool True db_minsize: int 1 db_maxsize: int 5 DEBUG: bool True test_abc:str 123 # 安全 secret_key: str dev-secret-key-123456-pydantic jwt_token_secret_key: str dhsjjdkfjdkfrjfrjgr-278783jkdsdhjdhjsds-dsdksjdkajskajieuiwueiwhdshmxzxno9iy token_expire_minutes: int 120 cors_allow_origins: list[str] [*] # 阿里云OSS ALIYUN_OSS_ACCESS_KEY_ID: str KEY ALIYUN_OSS_ACCESS_KEY_SECRET: str KEY ALIYUN_OSS_ENDPOINT: str oss-cn-beijing.aliyuncs.com ALIYUN_OSS_BUCKET_NAME: str fastapi-project-004 # 钉钉 DINGTALK_APP_KEY: str bf8ad584-a6d1-454d-8291-5e0158b4722b DINGTALK_REDIRECT_URI: str http://127.0.0.1:8000/third_party/dingtalk/login/callback DINGTALK_CLIENT_ID: str DINGTALK_CLIENT_SECRET: str REDIS_HOST: str 127.0.0.1 REDIS_PORT: int 6379 REDIS_DB: int 8 DEFAULT_AVATAR: str https://img10.360buyimg.com/pcpubliccms/s1440x1440_jfs/t1/240214/16/3793/62089/65acb64bF35c090ae/4cce5ee81fae5a23.jpg.avif # 高德地图 AMAP_SERVRER_KEY: str d0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 # 微信支付 V3 MCH_ID: str 1558950191 MCH_SERIAL_NO: str 34345964330B66427E0D3D28826C4993C77E631F PRIVATE_KEY_PATH: str apiclient_key.pem API_V3_KEY: str UDuLFDcmy5Eb6o0nTNZdu6ek4DDh4K8B APP_ID: str wx74862e0dfcf69954 DOMAIN: str https://api.mch.weixin.qq.com NOTIFY_DOMAIN: str https://xxx.ngrok.io PARTNER_KEY: str T6m9iK73b0kn9g5v426MKfHQH7X8rKwb property def NATIVE_ORDER_URL(self): return f{self.DOMAIN}/v3/pay/transactions/native property def QUERY_ORDER_URL(self): return f{self.DOMAIN}/v3/pay/transactions/id/ property def CLOSE_ORDER_URL(self): return f{self.DOMAIN}/v3/pay/transactions/out-trade-no/%s/close property def REFUND_URL(self): return f{self.DOMAIN}/v3/refund/domestic/refunds property def QUERY_REFUND_URL(self): return f{self.DOMAIN}/v3/refund/domestic/refunds/%s class TestAppSettings(BaseAppSettings): 测试环境 model_config SettingsConfigDict(env_file.env.test) server_port: int 8001 debug_mode: bool False db_url: str mysqlpymysql://root:123456localhost:3306/test_db secret_key: str test-secret-key-789012-pydantic cors_allow_origins: list[str] [https://test.yourdomain.com] class ProdAppSettings(BaseAppSettings): 生产环境 敏感配置 无默认值必须从环境变量或 .env.prod 读取 更安全、更规范 model_config SettingsConfigDict(env_file.env.prod) server_port: int 80 debug_mode: bool False cors_allow_origins: list[str] [https://yourdomain.com] # 生产必须配置不能为空 db_url: str secret_key: str jwt_token_secret_key: str db_host: str db_port: int db_user: str db_password: str db_name: str # 支付/OSS/第三方 全部从环境变量读取不写死代码 ALIYUN_OSS_ACCESS_KEY_ID: str ALIYUN_OSS_ACCESS_KEY_SECRET: str API_V3_KEY: str MCH_ID: str APP_ID: str # 环境枚举 SUPPORTED_ENVS [dev, test, prod] def get_app_settings(env: Optional[str] None) - BaseAppSettings: 多环境配置工厂标准写法 优先级传入参数 系统环境变量 默认 dev env env or os.getenv(FASTAPI_ENV, dev) if env not in SUPPORTED_ENVS: raise ValueError(f环境错误支持{SUPPORTED_ENVS}) env_map { dev: DevAppSettings, test: TestAppSettings, prod: ProdAppSettings, } return env_map[env]() # 全局唯一配置实例 settings get_app_settings()2.多环境配置一、什么是多环境配置依赖包pip install pydantic-settings多环境配置同一套业务代码在不同运行环境中加载不同的配置值。隔离不同场景的数据库、接口地址、密钥、开关等参数避免改代码切换环境。 常见环境dev开发环境本地开发、联调test测试环境测试人员验收pre预发环境线上镜像灰度验证prod生产环境正式对外服务

相关新闻

mac电脑 Maven下载安装和配置环境变量

mac电脑 Maven下载安装和配置环境变量

举例说明(任务):下载安装apache-maven-3.9.4 一、下载 1.Maven官网 Download Apache Maven – Mavenhttps://maven.apache.org/download.cgi 2.下载3.9.4 点击首页的Maven 3 archives ,所有的3.x.x的maven版本都在这Index of…

2026/7/22 8:51:05 阅读更多 →
Mac软件生态与M芯片优化工具全指南

Mac软件生态与M芯片优化工具全指南

1. Mac软件生态概述 作为一位深度使用Mac超过8年的老用户,我见证了macOS软件生态从匮乏到繁荣的完整演进过程。与Windows系统不同,Mac软件往往具有更统一的设计语言和更精致的交互体验,这也是许多创意工作者和开发者偏爱Mac的重要原因。但正因…

2026/7/22 8:50:05 阅读更多 →
代码之外的留白:一份关于Linux进程与文本的静谧笔记

代码之外的留白:一份关于Linux进程与文本的静谧笔记

引言:屏幕幽蓝,光标轻闪星光璀璨,前路漫漫 ——作者在图形化界面(GUI)统治的今天,我们习惯…

2026/7/22 8:50:05 阅读更多 →

最新新闻

成都网站建设公司怎么找?5个标准判断建站服务商是否专业

成都网站建设公司怎么找?5个标准判断建站服务商是否专业

据CNNIC第55次《中国互联网络发展状况统计报告》,截至2025年12月,中国网站数量为432万个,但其中超过60%的中小企业网站月均自然访问量不足100人次。这不是网站这个形态的问题——问题是怎么做。成都市2025年建站市场规模约12亿元(…

2026/7/22 9:39:23 阅读更多 →
腾讯云部署OpenClaw AI助手:8分钟快速搭建指南

腾讯云部署OpenClaw AI助手:8分钟快速搭建指南

1. OpenClaw项目概述 OpenClaw(Clawdbot)是当前炙手可热的AI生活助理解决方案,它通过智能对话接口实现与ClaudeCode等AI系统的无缝协作。作为支持多平台部署的自动化工具,其核心价值在于将复杂的AI能力封装成简单易用的服务接口。…

2026/7/22 9:39:23 阅读更多 →
如何验证你买的软件激活码,是正版还是盗版?

如何验证你买的软件激活码,是正版还是盗版?

如果本文对你有帮助,想选购正版软件,或查看更多软件技巧 & 资讯,欢迎搜索“数码荔枝”或访问网站 lizhi.shop很多人买正版软件,最担心的往往不是“能不能激活”,而是: 激活码是否正规;授权是…

2026/7/22 9:39:23 阅读更多 →
2026年AI原生开发趋势与实战案例解析

2026年AI原生开发趋势与实战案例解析

1. 2026年AI原生开发趋势解读 2026年将成为AI原生开发的关键转折点。作为一名长期跟踪AI技术演进的开发者,我观察到几个显著变化:首先是开发范式的转变,传统"AI作为附加功能"的模式正在被"AI First"的原生开发理念取代&a…

2026/7/22 9:39:23 阅读更多 →
PortSwigger SQL注入LAB5  LAB6

PortSwigger SQL注入LAB5 LAB6

断列数,最后把数据库中的结构信息回显到页面里。 但它们的数据库环境并不一样:一题侧重 MySQL,另一题侧重 Oracle。正因为如此,注释符、系统视图这些细节会有差别,所以我把这两个 LAB 放在一起来分享,也顺便…

2026/7/22 9:39:23 阅读更多 →
Unity 2021.3与Pico SDK 230实现VR手势交互开发全流程

Unity 2021.3与Pico SDK 230实现VR手势交互开发全流程

1. 项目概述:为什么选择手势交互?最近在做一个面向Pico Neo 3/4的VR项目,客户明确要求“去手柄化”,希望用户能像电影里那样,直接用手势来操作界面、抓取物体。这其实反映了当前VR内容发展的一个趋势:从依赖…

2026/7/22 9:38:23 阅读更多 →

日新闻

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

1. 项目概述与SYSCFG模块的核心价值在嵌入式系统,尤其是像TI C6000系列这样的高性能DSP开发中,我们常常会与芯片手册里那些密密麻麻的寄存器打交道。很多开发者可能更关注算法实现、内存优化或者外设驱动,但对于一个稳定、高效的系统而言&…

2026/7/22 0:00:26 阅读更多 →
微信Server酱:高到达率的应急通知方案实践

微信Server酱:高到达率的应急通知方案实践

1. 为什么我们需要"最次"的通知方案? 在数字化协作环境中,消息通知系统的重要性不言而喻明。但现实情况是,企业级通知方案往往需要复杂的API对接(如企业微信、钉钉、飞书),个人开发者的小项目又经…

2026/7/22 0:00:26 阅读更多 →
甲方要的“简洁“PPT,到底是简洁还是省事?

甲方要的“简洁“PPT,到底是简洁还是省事?

甲方说"简洁一点",乙方听到的是"少做几页"。甲方说"不要太复杂",乙方理解成"别放图表了"。结果交过去,甲方说"我说的简洁不是这个意思"。"简洁"这个词在PPT语境里,是…

2026/7/22 0:00:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 5:34:47 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 8:25:39 阅读更多 →

月新闻