From 9751bf20b0eb0506af2c9d134399a8997b6d5eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E7=85=9C?= Date: Sun, 28 Sep 2025 08:40:27 +0800 Subject: [PATCH] =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 6 ++- .env | 38 +++++++++++++++ .env.dev | 11 ++++- .env.example | 95 ++++++++++++++++++------------------- .env.prod | 48 +++++++++++++++++++ .env.test | 20 ++++++++ CLAUDE.md | 57 ++++++++++++++++++---- app/core/config.py | 25 +++++----- 8 files changed, 228 insertions(+), 72 deletions(-) create mode 100644 .env create mode 100644 .env.prod create mode 100644 .env.test diff --git a/.claude/settings.local.json b/.claude/settings.local.json index a974f46..ce59710 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -5,7 +5,11 @@ "Bash(curl:*)", "Bash(git init:*)", "Bash(git remote:*)", - "Bash(git add:*)" + "Bash(git add:*)", + "Bash(git push:*)", + "Bash(pip install:*)", + "Bash(set ENVIRONMENT=development)", + "Bash(dir:*)" ], "deny": [], "ask": [] diff --git a/.env b/.env new file mode 100644 index 0000000..64bde50 --- /dev/null +++ b/.env @@ -0,0 +1,38 @@ +# 开发环境配置 +PROJECT_NAME=FastAPI Demo +VERSION=1.0.0 +DEBUG=True +ENVIRONMENT=development + +# 服务器配置 +HOST=0.0.0.0 +PORT=8000 +LOG_LEVEL=info + +# MySQL 数据库配置 +DB_HOST=localhost +DB_PORT=3306 +DB_USER=root +DB_PASSWORD=123456 +DB_NAME=fast_demo +DB_CHARSET=utf8mb4 + +# 数据库连接池配置 +DB_ECHO=False +DB_POOL_SIZE=5 +DB_MAX_OVERFLOW=10 +DB_POOL_TIMEOUT=30 +DB_POOL_RECYCLE=3600 + +# Redis 配置(可选) +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_DB=0 + +# CORS 配置 +CORS_ORIGINS=["*"] + +# JWT 配置 +SECRET_KEY=your-secret-key-here-change-in-production +ACCESS_TOKEN_EXPIRE_MINUTES=30 +REFRESH_TOKEN_EXPIRE_DAYS=7 \ No newline at end of file diff --git a/.env.dev b/.env.dev index ff918d0..03453f6 100644 --- a/.env.dev +++ b/.env.dev @@ -18,11 +18,18 @@ DOCS_URL=/docs REDOC_URL=/redoc # 数据库配置 -# 当前使用内存模拟数据库,无需真实数据库连接 -# DATABASE_URL=sqlite:///./app.db +# MySQL 数据库连接(开发环境) +DB_HOST=localhost +DB_PORT=3306 +DB_USER=root +DB_PASSWORD=123456 +DB_NAME=fast_demo +DB_CHARSET=utf8mb4 DB_ECHO=True DB_POOL_SIZE=5 DB_MAX_OVERFLOW=10 +DB_POOL_TIMEOUT=30 +DB_POOL_RECYCLE=3600 # CORS 配置 CORS_ORIGINS=["http://localhost:3000","http://localhost:8080"] diff --git a/.env.example b/.env.example index e5df0fb..9d3e03b 100644 --- a/.env.example +++ b/.env.example @@ -1,73 +1,72 @@ -# 应用基础配置 +# FastAPI 演示项目环境配置模板 +# 复制此文件为 .env 并根据实际情况修改配置 + +# === 应用基础配置 === PROJECT_NAME=FastAPI Demo VERSION=1.0.0 -DESCRIPTION=A simple FastAPI learning project DEBUG=True ENVIRONMENT=development -# 服务器配置 +# === 服务器配置 === HOST=0.0.0.0 PORT=8000 -WORKERS=1 -RELOAD=True LOG_LEVEL=info +# WORKERS=1 # 生产环境可设置多个 worker +# RELOAD=True # 开发环境开启热重载 -# API 配置 -API_V1_STR=/api/v1 -DOCS_URL=/docs -REDOC_URL=/redoc +# === MySQL 数据库配置 === +# 请根据实际环境修改数据库连接信息 +DB_HOST=localhost +DB_PORT=3306 +DB_USER=your_db_user +DB_PASSWORD=your_db_password +DB_NAME=your_database_name +DB_CHARSET=utf8mb4 -# 数据库配置 -DATABASE_URL=postgresql://user:password@localhost/dbname -# DATABASE_URL=mysql://user:password@localhost/dbname -# DATABASE_URL=sqlite:///./app.db -DB_ECHO=True +# === 数据库连接池配置 === +DB_ECHO=False # 开启后会打印 SQL 语句,调试时可设为 True DB_POOL_SIZE=5 DB_MAX_OVERFLOW=10 +DB_POOL_TIMEOUT=30 +DB_POOL_RECYCLE=3600 -# Redis 配置 +# === Redis 配置(可选) === REDIS_HOST=localhost REDIS_PORT=6379 REDIS_DB=0 -REDIS_PASSWORD= +# REDIS_PASSWORD=your_redis_password -# CORS 配置 -CORS_ORIGINS=["http://localhost:3000","http://localhost:8080"] -CORS_ALLOW_CREDENTIALS=True -CORS_ALLOW_METHODS=["*"] -CORS_ALLOW_HEADERS=["*"] +# === CORS 配置 === +# 开发环境允许所有来源,生产环境应指定具体域名 +CORS_ORIGINS=["*"] +# 生产环境示例:CORS_ORIGINS=["https://yourdomain.com","https://api.yourdomain.com"] -# JWT 认证配置 +# === JWT 配置 === +# 生产环境必须使用强密钥(至少32个字符) SECRET_KEY=your-secret-key-here-change-in-production -ALGORITHM=HS256 ACCESS_TOKEN_EXPIRE_MINUTES=30 REFRESH_TOKEN_EXPIRE_DAYS=7 -# 邮件配置 -SMTP_HOST=smtp.gmail.com -SMTP_PORT=587 -SMTP_USER=your-email@gmail.com -SMTP_PASSWORD=your-password -SMTP_FROM=noreply@example.com +# === API 文档配置 === +# 生产环境建议关闭 API 文档 +# DOCS_URL=/docs +# REDOC_URL=/redoc +# 关闭文档示例: +# DOCS_URL= +# REDOC_URL= -# 文件上传配置 -UPLOAD_DIR=./uploads -MAX_UPLOAD_SIZE=10485760 # 10MB in bytes -ALLOWED_EXTENSIONS=["jpg","jpeg","png","pdf","doc","docx"] +# === 邮件配置(可选) === +# SMTP_HOST=smtp.yourdomain.com +# SMTP_PORT=587 +# SMTP_USER=noreply@yourdomain.com +# SMTP_PASSWORD=your_smtp_password +# SMTP_FROM=noreply@yourdomain.com -# 第三方 API 配置 -OPENAI_API_KEY= -STRIPE_API_KEY= -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_REGION=us-east-1 +# === 监控配置(可选) === +# SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id +# PROMETHEUS_ENABLED=True -# 监控配置 -SENTRY_DSN= -PROMETHEUS_ENABLED=False -METRICS_PATH=/metrics - -# 限流配置 -RATE_LIMIT_ENABLED=True -RATE_LIMIT_REQUESTS=100 -RATE_LIMIT_PERIOD=60 # seconds \ No newline at end of file +# === 限流配置(可选) === +# RATE_LIMIT_ENABLED=True +# RATE_LIMIT_REQUESTS=100 +# RATE_LIMIT_PERIOD=60 \ No newline at end of file diff --git a/.env.prod b/.env.prod new file mode 100644 index 0000000..fd860f1 --- /dev/null +++ b/.env.prod @@ -0,0 +1,48 @@ +# 生产环境配置 +ENVIRONMENT=production +DEBUG=False +LOG_LEVEL=info + +# 服务器配置 +HOST=127.0.0.1 +PORT=8000 +WORKERS=4 +RELOAD=False + +# 生产环境关闭 API 文档 +DOCS_URL= +REDOC_URL= + +# 数据库 - 生产环境使用 PostgreSQL +DATABASE_URL=postgresql://user:password@localhost/prod_db +DB_ECHO=False +DB_POOL_SIZE=20 +DB_MAX_OVERFLOW=30 + +# Redis 配置 +REDIS_HOST=prod-redis-server +REDIS_PASSWORD=your-redis-password + +# CORS 严格限制 +CORS_ORIGINS=["https://yourdomain.com","https://www.yourdomain.com"] + +# JWT 配置 - 生产环境必须使用强密钥 +SECRET_KEY=your-super-secret-key-at-least-32-characters-long +ACCESS_TOKEN_EXPIRE_MINUTES=15 +REFRESH_TOKEN_EXPIRE_DAYS=7 + +# 邮件配置 +SMTP_HOST=smtp.yourdomain.com +SMTP_PORT=587 +SMTP_USER=noreply@yourdomain.com +SMTP_PASSWORD=your-smtp-password +SMTP_FROM=noreply@yourdomain.com + +# 监控配置 +SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id +PROMETHEUS_ENABLED=True + +# 限流配置 +RATE_LIMIT_ENABLED=True +RATE_LIMIT_REQUESTS=100 +RATE_LIMIT_PERIOD=60 \ No newline at end of file diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..62bfd3e --- /dev/null +++ b/.env.test @@ -0,0 +1,20 @@ +# 测试环境配置 +ENVIRONMENT=testing +DEBUG=False +LOG_LEVEL=warning + +# 测试数据库 +DATABASE_URL=sqlite:///./test.db +DB_ECHO=False + +# API 文档在测试环境关闭 +DOCS_URL= +REDOC_URL= + +# CORS 严格限制 +CORS_ORIGINS=["http://localhost:3000"] + +# 限流配置 +RATE_LIMIT_ENABLED=True +RATE_LIMIT_REQUESTS=50 +RATE_LIMIT_PERIOD=60 \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 6745cfd..3739da9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,13 +10,16 @@ pip install -r requirements.txt pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ -# 1. 直接运行(使用 .env.dev 或默认配置) +# 安装数据库驱动 +pip install sqlalchemy pymysql -i https://mirrors.aliyun.com/pypi/simple/ + +# 1. 直接运行(使用 .env 或默认配置) python main.py # 2. 指定环境运行(推荐) -ENVIRONMENT=development python main.py # 使用 .env.dev.dev 配置 -ENVIRONMENT=testing python main.py # 使用 .env.dev.test 配置 -ENVIRONMENT=production python main.py # 使用 .env.dev.prod 配置 +ENVIRONMENT=development python main.py # 使用 .env.dev 配置 +ENVIRONMENT=testing python main.py # 使用 .env.test 配置 +ENVIRONMENT=production python main.py # 使用 .env.prod 配置 # 3. Windows 系统设置环境变量 set ENVIRONMENT=development && python main.py @@ -45,10 +48,39 @@ python start.py --env dev --reload # 开发环境+强制热重载 ### 配置管理 ```bash # 复制环境配置模板 -cp .env.dev.example .env.dev +cp .env.example .env +# 编辑 .env 文件,修改数据库连接等配置 # 查看当前配置 python -c "from app.core.config import settings; print(f'Environment: {settings.ENVIRONMENT}'); print(f'Debug: {settings.DEBUG}')" + +# 配置文件说明 +# .env - 当前环境配置(不提交到 git) +# .env.example - 配置模板文件(提交到 git) +# .env.prod - 生产环境配置示例 +# .env.test - 测试环境配置示例 +``` + +### 数据库设置 +```bash +# MySQL 数据库配置 +# 1. 创建数据库 +mysql -u root -p +CREATE DATABASE fast_demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +# 2. 配置数据库连接 +# 复制配置模板并修改数据库连接信息 +cp .env.example .env +# 编辑 .env 文件,修改以下配置: +# DB_HOST=localhost # 数据库主机 +# DB_PORT=3306 # 数据库端口 +# DB_USER=root # 数据库用户 +# DB_PASSWORD=123456 # 数据库密码 +# DB_NAME=fast_demo # 数据库名称 + +# 3. 应用启动时会自动创建表结构 +# - users 表:用户信息 +# - products 表:产品信息 ``` ### 测试 API @@ -59,6 +91,10 @@ python -c "from app.core.config import settings; print(f'Environment: {settings. # 健康检查端点 curl http://localhost:8000/health + +# API 端点示例 +curl http://localhost:8000/api/v1/users/ # 获取用户列表 +curl http://localhost:8000/api/v1/products/ # 获取产品列表 ``` ## 架构说明 @@ -72,7 +108,9 @@ curl http://localhost:8000/health - **API 层** (`app/api/v1/endpoints/`):处理 HTTP 请求和响应的 FastAPI 路由器。每个路由器对应一个资源(用户、产品)并定义 API 端点。 -- **服务层** (`app/services/`):使用静态服务类实现业务逻辑。目前使用内存中的模拟数据库进行演示。服务处理 CRUD 操作和业务规则。 +- **服务层** (`app/services/`):使用服务类实现业务逻辑,通过 SQLAlchemy ORM 与 MySQL 数据库交互。服务处理 CRUD 操作和业务规则。 + +- **数据库层** (`app/database/`):数据库连接配置和会话管理,使用 SQLAlchemy 连接 MySQL 数据库。 - **模式层** (`app/schemas/`):用于请求/响应验证和序列化的 Pydantic 模型。为每个实体遵循 Base、Create、Update 和 Response 模型的模式。 @@ -92,7 +130,7 @@ curl http://localhost:8000/health 5. **模式分离**:为不同操作(Create、Update、Response)设置不同的模式,在 API 设计中提供灵活性,而不暴露内部模型细节。 -6. **内存数据存储**:目前使用内存中的模拟列表进行数据存储。这是有意为演示而设计的 - 实际实现将在服务层中集成数据库。 +6. **数据库存储**:项目已集成 MySQL 数据库,使用 SQLAlchemy ORM 进行数据持久化。支持自动创建表结构和数据迁移。 7. **CORS 中间件**:配置了宽松的设置(`allow_origins=["*"]`)适合开发环境。生产环境中应该限制。 @@ -109,9 +147,10 @@ curl http://localhost:8000/health - 代码中的默认值 2. **多环境配置**: - - `.env.dev` - 开发环境:调试开启、允许所有CORS、使用SQLite + - `.env` - 基础配置:默认使用 MySQL 数据库 + - `.env.dev` - 开发环境:调试开启、允许所有CORS、使用 MySQL - `.env.test` - 测试环境:关闭API文档、严格限流、测试数据库 - - `.env.prod` - 生产环境:关闭调试、使用PostgreSQL、启用监控 + - `.env.prod` - 生产环境:关闭调试、使用 PostgreSQL、启用监控 3. **配置特性**: - 类型验证和转换 diff --git a/app/core/config.py b/app/core/config.py index ac75eb5..fe13744 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -30,13 +30,13 @@ class Settings(BaseSettings): REDOC_URL: Optional[str] = "/redoc" # === 数据库配置 === - # MySQL 数据库配置 - DB_HOST: str = "localhost" - DB_PORT: int = 3306 - DB_USER: str = "root" - DB_PASSWORD: str = "123456" - DB_NAME: str = "fast_demo" - DB_CHARSET: str = "utf8mb4" + # MySQL 数据库配置(从环境变量或 .env 文件读取) + DB_HOST: str = Field(default="localhost", description="数据库主机地址") + DB_PORT: int = Field(default=3306, description="数据库端口") + DB_USER: str = Field(default="root", description="数据库用户名") + DB_PASSWORD: str = Field(default="", description="数据库密码") + DB_NAME: str = Field(default="fastapi_demo", description="数据库名称") + DB_CHARSET: str = Field(default="utf8mb4", description="数据库字符集") # 数据库连接池配置 DB_ECHO: bool = False @@ -128,7 +128,7 @@ class Settings(BaseSettings): return self.ENVIRONMENT == "testing" class Config: - env_file = ".env.dev" + env_file = ".env" env_file_encoding = "utf-8" case_sensitive = True @@ -139,13 +139,14 @@ def get_settings() -> Settings: import os env = os.getenv("ENVIRONMENT", "development") - env_files = [".env.dev"] + # 优先级:环境特定配置 > .env 通用配置 + env_files = [".env"] if env == "development": - env_files.append(".env.dev.dev") + env_files.append(".env.dev") elif env == "testing": - env_files.append(".env.dev.test") + env_files.append(".env.test") elif env == "production": - env_files.append(".env.dev.prod") + env_files.append(".env.prod") # 尝试加载对应的环境配置文件 for env_file in reversed(env_files):