modify: config sqlite 配置规范
This commit is contained in:
@@ -1,22 +1,30 @@
|
|||||||
[default]
|
[default]
|
||||||
app.name = "{{ cookiecutter.project_name }}"
|
app.name = "{{ cookiecutter.project_name }}"
|
||||||
app.version = "{{ cookiecutter.author_name }}"
|
app.version = "{{ cookiecutter.project_name }}"
|
||||||
app.description = "基于 FastAPI 和 Tortoise-ORM 的 chongming 打包脚手架"
|
app.description = "基于 FastAPI 和 Tortoise-ORM 的 chongming 打包脚手架"
|
||||||
app.debug = false
|
app.debug = false
|
||||||
# env = "production"
|
# env = "production"
|
||||||
|
|
||||||
[server]
|
|
||||||
host = "0.0.0.0"
|
|
||||||
port = 8000
|
|
||||||
reload = false
|
|
||||||
workers = 4
|
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
url = "sqlite://db.sqlite3"
|
type = "sqlite"
|
||||||
# PostgreSQL 示例: "postgres://user:pass@localhost:5432/dbname"
|
|
||||||
# MySQL 示例: "mysql://user:pass@localhost:3306/dbname"
|
|
||||||
generate_schemas = true # 生产环境使用迁移工具
|
generate_schemas = true # 生产环境使用迁移工具
|
||||||
|
|
||||||
|
[database.sqlite]
|
||||||
|
engine = "tortoise.backends.sqlite"
|
||||||
|
file_path = "db.sqlite3"
|
||||||
|
journal_mode = "WAL"
|
||||||
|
busy_timeout = 10000
|
||||||
|
maxsize = 10
|
||||||
|
minsize = 1
|
||||||
|
cache_size = -2000
|
||||||
|
synchronous = "NORMAL"
|
||||||
|
temp_store = "MEMORY"
|
||||||
|
mmap_size = 1073741824
|
||||||
|
foreign_keys = true
|
||||||
|
auto_vacuum = "INCREMENTAL"
|
||||||
|
max_cached_statements = 100
|
||||||
|
readonly = false
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
secret_key = "your-secret-key-change-in-production"
|
secret_key = "your-secret-key-change-in-production"
|
||||||
algorithm = "HS256"
|
algorithm = "HS256"
|
||||||
@@ -32,10 +40,6 @@ port = 8000
|
|||||||
reload = true
|
reload = true
|
||||||
# workers = 4
|
# workers = 4
|
||||||
|
|
||||||
[development.database]
|
|
||||||
url = "sqlite://dev.db"
|
|
||||||
generate_schemas = true
|
|
||||||
|
|
||||||
[development.logging]
|
[development.logging]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
file = "logs/dev.log"
|
file = "logs/dev.log"
|
||||||
@@ -56,16 +60,12 @@ port = 8000
|
|||||||
reload = false
|
reload = false
|
||||||
workers = 1
|
workers = 1
|
||||||
|
|
||||||
[production.database]
|
|
||||||
url = "sqlite://prod.db"
|
|
||||||
generate_schemas = true
|
|
||||||
|
|
||||||
[production.logging]
|
[production.logging]
|
||||||
level = "INFO"
|
level = "INFO"
|
||||||
file = "logs/prod.log"
|
file = "logs/prod.log"
|
||||||
|
|
||||||
[production.cors]
|
[production.cors]
|
||||||
allow_origins = ["https://yourdomain.com"]
|
allow_origins = ["https://yourdomain.com", "http://localhos:8000", "http://127.0.0.1:8000"]
|
||||||
allow_credentials = true
|
allow_credentials = true
|
||||||
allow_methods = ["GET", "POST", "PUT", "DELETE"]
|
allow_methods = ["GET", "POST", "PUT", "DELETE"]
|
||||||
allow_headers = ["Authorization", "Content-Type"]
|
allow_headers = ["Authorization", "Content-Type"]
|
||||||
@@ -78,9 +78,5 @@ path = ["resources/app.mbank", "resources/plugins.mbank"]
|
|||||||
type = "svfs"
|
type = "svfs"
|
||||||
path = "resources/application.vfs"
|
path = "resources/application.vfs"
|
||||||
|
|
||||||
[redis]
|
|
||||||
enabled = false
|
|
||||||
url = "redis://localhost:6379"
|
|
||||||
|
|
||||||
[cache]
|
[cache]
|
||||||
default_ttl = 300
|
default_ttl = 300
|
||||||
|
|||||||
@@ -1,22 +1,30 @@
|
|||||||
[default]
|
[default]
|
||||||
app.name = "{{ cookiecutter.project_name }}"
|
app.name = "{{ cookiecutter.project_name }}"
|
||||||
app.version = "{{ cookiecutter.author_name }}"
|
app.version = "{{ cookiecutter.project_name }}"
|
||||||
app.description = "基于 FastAPI 和 Tortoise-ORM 的 chongming 打包脚手架"
|
app.description = "基于 FastAPI 和 Tortoise-ORM 的 chongming 打包脚手架"
|
||||||
app.debug = false
|
app.debug = false
|
||||||
env = "production"
|
env = "production"
|
||||||
|
|
||||||
[server]
|
|
||||||
host = "0.0.0.0"
|
|
||||||
port = 8000
|
|
||||||
reload = false
|
|
||||||
workers = 4
|
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
url = "sqlite://db.sqlite3"
|
type = "sqlite"
|
||||||
# PostgreSQL 示例: "postgres://user:pass@localhost:5432/dbname"
|
|
||||||
# MySQL 示例: "mysql://user:pass@localhost:3306/dbname"
|
|
||||||
generate_schemas = true # 生产环境使用迁移工具
|
generate_schemas = true # 生产环境使用迁移工具
|
||||||
|
|
||||||
|
[database.sqlite]
|
||||||
|
engine = "tortoise.backends.sqlite"
|
||||||
|
file_path = "db.sqlite3"
|
||||||
|
journal_mode = "WAL"
|
||||||
|
busy_timeout = 10000
|
||||||
|
maxsize = 10
|
||||||
|
minsize = 1
|
||||||
|
cache_size = -2000
|
||||||
|
synchronous = "NORMAL"
|
||||||
|
temp_store = "MEMORY"
|
||||||
|
mmap_size = 1073741824
|
||||||
|
foreign_keys = true
|
||||||
|
auto_vacuum = "INCREMENTAL"
|
||||||
|
max_cached_statements = 100
|
||||||
|
readonly = false
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
secret_key = "your-secret-key-change-in-production"
|
secret_key = "your-secret-key-change-in-production"
|
||||||
algorithm = "HS256"
|
algorithm = "HS256"
|
||||||
@@ -32,10 +40,6 @@ port = 8000
|
|||||||
reload = true
|
reload = true
|
||||||
# workers = 4
|
# workers = 4
|
||||||
|
|
||||||
[development.database]
|
|
||||||
url = "sqlite://dev.db"
|
|
||||||
generate_schemas = true
|
|
||||||
|
|
||||||
[development.logging]
|
[development.logging]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
file = "logs/dev.log"
|
file = "logs/dev.log"
|
||||||
@@ -56,16 +60,12 @@ port = 8000
|
|||||||
reload = false
|
reload = false
|
||||||
workers = 1
|
workers = 1
|
||||||
|
|
||||||
[production.database]
|
|
||||||
url = "sqlite://prod.db"
|
|
||||||
generate_schemas = true
|
|
||||||
|
|
||||||
[production.logging]
|
[production.logging]
|
||||||
level = "INFO"
|
level = "INFO"
|
||||||
file = "logs/prod.log"
|
file = "logs/prod.log"
|
||||||
|
|
||||||
[production.cors]
|
[production.cors]
|
||||||
allow_origins = ["https://yourdomain.com"]
|
allow_origins = ["https://yourdomain.com", "http://localhos:8000", "http://127.0.0.1:8000"]
|
||||||
allow_credentials = true
|
allow_credentials = true
|
||||||
allow_methods = ["GET", "POST", "PUT", "DELETE"]
|
allow_methods = ["GET", "POST", "PUT", "DELETE"]
|
||||||
allow_headers = ["Authorization", "Content-Type"]
|
allow_headers = ["Authorization", "Content-Type"]
|
||||||
@@ -78,9 +78,5 @@ path = ["resources/app.mbank", "resources/plugins.mbank"]
|
|||||||
type = "svfs"
|
type = "svfs"
|
||||||
path = "resources/application.vfs"
|
path = "resources/application.vfs"
|
||||||
|
|
||||||
[redis]
|
|
||||||
enabled = false
|
|
||||||
url = "redis://localhost:6379"
|
|
||||||
|
|
||||||
[cache]
|
[cache]
|
||||||
default_ttl = 300
|
default_ttl = 300
|
||||||
|
|||||||
+139
-76
@@ -1,135 +1,198 @@
|
|||||||
"""
|
"""
|
||||||
配置管理模块
|
配置管理模块 - 简化版本
|
||||||
基于 Pydantic Settings 和 TOML 文件
|
基于 Pydantic Settings 和 TOML 文件
|
||||||
"""
|
"""
|
||||||
from typing import Optional, Dict, Any
|
|
||||||
|
from typing import Optional, List, Dict, Any
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
from pydantic import Field
|
from pydantic import model_validator
|
||||||
import toml
|
import toml
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
try:
|
try:
|
||||||
from ...utils.launch import args
|
from ...utils.launch import args
|
||||||
except:
|
except:
|
||||||
from utils.launch import args # type: ignore
|
from utils.launch import args # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class SQLiteConfig(BaseSettings):
|
||||||
|
"""SQLite 配置"""
|
||||||
|
|
||||||
|
engine: str = "tortoise.backends.sqlite"
|
||||||
|
file_path: str = "db.sqlite3"
|
||||||
|
journal_mode: str = "WAL"
|
||||||
|
busy_timeout: int = 10000
|
||||||
|
maxsize: int = 10
|
||||||
|
minsize: int = 1
|
||||||
|
cache_size: int = -2000
|
||||||
|
synchronous: str = "NORMAL"
|
||||||
|
temp_store: str = "MEMORY"
|
||||||
|
mmap_size: int = 1073741824
|
||||||
|
foreign_keys: bool = True
|
||||||
|
auto_vacuum: str = "INCREMENTAL"
|
||||||
|
max_cached_statements: int = 100
|
||||||
|
readonly: bool = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tortoise_config(self) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"default": {
|
||||||
|
"engine": self.engine,
|
||||||
|
"credentials": {
|
||||||
|
"file_path": self.file_path,
|
||||||
|
"journal_mode": self.journal_mode,
|
||||||
|
"busy_timeout": self.busy_timeout,
|
||||||
|
"maxsize": self.maxsize,
|
||||||
|
"minsize": self.minsize,
|
||||||
|
"cache_size": self.cache_size,
|
||||||
|
"synchronous": self.synchronous,
|
||||||
|
"temp_store": self.temp_store,
|
||||||
|
"mmap_size": self.mmap_size,
|
||||||
|
"foreign_keys": self.foreign_keys,
|
||||||
|
"auto_vacuum": self.auto_vacuum,
|
||||||
|
"max_cached_statements": self.max_cached_statements,
|
||||||
|
"readonly": self.readonly,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
"""应用配置"""
|
"""应用配置"""
|
||||||
|
|
||||||
# 应用信息
|
# 应用信息
|
||||||
app_name: str = "FastAPI Demo"
|
app_name: str = "FastAPI Demo"
|
||||||
app_version: str = "1.0.0"
|
app_version: str = "1.0.0"
|
||||||
description: str = "FastAPI 应用"
|
description: str = "FastAPI 应用"
|
||||||
|
|
||||||
# 服务器配置
|
# 服务器配置
|
||||||
host: str = "0.0.0.0"
|
host: str = "0.0.0.0"
|
||||||
port: int = 8000
|
port: int = 8000
|
||||||
reload: bool = False
|
reload: bool = False
|
||||||
workers: int = 4
|
workers: int = 1 # 开发环境默认1,避免与 reload 冲突
|
||||||
|
|
||||||
# 数据库配置
|
database_type: str = "sqlite"
|
||||||
database_url: str = "sqlite://db.sqlite3"
|
|
||||||
generate_schemas: bool = False
|
# SQLite 配置
|
||||||
|
sqlite_config: SQLiteConfig = SQLiteConfig()
|
||||||
|
|
||||||
# 环境配置
|
# 环境配置
|
||||||
env: str = "development"
|
env: str = "development"
|
||||||
debug: bool = False
|
debug: bool = False
|
||||||
|
|
||||||
|
# 数据库配置
|
||||||
|
generate_schemas: bool = False
|
||||||
|
|
||||||
# 日志配置
|
# 日志配置
|
||||||
logging_level: str = "INFO"
|
logging_level: str = "INFO"
|
||||||
logging_file: Optional[str] = None
|
logging_file: Optional[str] = None
|
||||||
|
|
||||||
# CORS 配置
|
# CORS 配置
|
||||||
cors_allow_origins: list = ["*"]
|
cors_allow_origins: List[str] = ["*"]
|
||||||
cors_allow_credentials: bool = True
|
cors_allow_credentials: bool = True
|
||||||
cors_allow_methods: list = ["*"]
|
cors_allow_methods: List[str] = ["*"]
|
||||||
cors_allow_headers: list = ["*"]
|
cors_allow_headers: List[str] = ["*"]
|
||||||
|
|
||||||
# 安全配置
|
# 安全配置
|
||||||
secret_key: str = "your-secret-key-change-in-production"
|
secret_key: str = "your-secret-key-change-in-production"
|
||||||
algorithm: str = "HS256"
|
algorithm: str = "HS256"
|
||||||
access_token_expire_minutes: int = 30
|
access_token_expire_minutes: int = 30
|
||||||
|
|
||||||
# 模块系统
|
# 模块系统
|
||||||
module_system_type: str = "local"
|
module_system_type: str = "local"
|
||||||
module_system_path: list = ["plugins", "app"]
|
module_system_path: List[str] = ["plugins", "app"]
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
env_file = ".env"
|
env_file = ".env"
|
||||||
extra = "ignore"
|
extra = "ignore"
|
||||||
|
|
||||||
|
@model_validator(mode="after")
|
||||||
|
def validate_settings(self):
|
||||||
|
"""验证和调整设置"""
|
||||||
|
# 如果启用 reload,workers 必须为 1
|
||||||
|
if self.reload and self.workers != 1:
|
||||||
|
print(f"⚠️ reload 启用,将 workers 从 {self.workers} 调整为 1")
|
||||||
|
self.workers = 1
|
||||||
|
return self
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_toml(cls, config_path: Optional[str] = None) -> "Settings":
|
def from_toml(cls, config_path: Optional[str] = None) -> "Settings":
|
||||||
"""从 TOML 文件加载配置"""
|
"""从 TOML 文件加载配置 - 简化版本"""
|
||||||
|
|
||||||
|
# 1. 确定配置文件路径
|
||||||
if config_path is None:
|
if config_path is None:
|
||||||
# 尝试多个可能的配置路径
|
config_path = "config.toml"
|
||||||
possible_paths = [
|
|
||||||
"config.toml",
|
config_file = Path(config_path)
|
||||||
"./config.toml",
|
if not config_file.exists():
|
||||||
"../config.toml",
|
print(f"⚠️ 配置文件不存在: {config_path},使用默认配置")
|
||||||
Path(__file__).parent.parent.parent / "config.toml",
|
return cls()
|
||||||
]
|
|
||||||
|
|
||||||
for path in possible_paths:
|
|
||||||
if Path(path).exists():
|
|
||||||
config_path = str(path)
|
|
||||||
print(f"📄 加载配置文件: {config_path}")
|
|
||||||
break
|
|
||||||
|
|
||||||
if config_path is None:
|
|
||||||
print("⚠️ 未找到配置文件,使用默认配置")
|
|
||||||
return cls()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config_file = Path(config_path)
|
# 2. 加载 TOML 文件
|
||||||
if not config_file.exists():
|
|
||||||
print(f"⚠️ 配置文件不存在: {config_path}")
|
|
||||||
return cls()
|
|
||||||
|
|
||||||
config_data = toml.load(config_file)
|
config_data = toml.load(config_file)
|
||||||
|
print(f"📄 加载配置文件: {config_path}")
|
||||||
# 获取默认配置
|
|
||||||
|
# 3. 确定环境
|
||||||
default_config = config_data.get("default", {})
|
default_config = config_data.get("default", {})
|
||||||
|
|
||||||
# 确定环境
|
|
||||||
env = default_config.get("env", "development")
|
env = default_config.get("env", "development")
|
||||||
|
|
||||||
# 获取环境特定配置
|
|
||||||
env_config = config_data.get(env, {})
|
|
||||||
|
|
||||||
# 合并配置
|
|
||||||
merged_config = {**default_config, **env_config}
|
|
||||||
|
|
||||||
# 处理嵌套配置
|
|
||||||
for section in ["server", "database", "security", "logging", "cors", "module_system"]:
|
|
||||||
if section in config_data:
|
|
||||||
if isinstance(config_data[section], dict):
|
|
||||||
merged_config.update(config_data[section])
|
|
||||||
|
|
||||||
# 从环境特定配置中覆盖
|
|
||||||
for section in ["server", "database", "security", "logging", "cors", "module_system"]:
|
|
||||||
env_section_key = f"{env}.{section}"
|
|
||||||
if env_section_key in config_data:
|
|
||||||
if isinstance(config_data[env_section_key], dict):
|
|
||||||
merged_config.update(config_data[env_section_key])
|
|
||||||
|
|
||||||
print(f"🌍 环境: {env}")
|
print(f"🌍 环境: {env}")
|
||||||
return cls(**merged_config)
|
|
||||||
|
# 4. 获取环境特定配置
|
||||||
|
env_config = config_data.get(env, {})
|
||||||
|
|
||||||
|
# 5. 构建配置字典
|
||||||
|
config_dict = {}
|
||||||
|
|
||||||
|
# 5.1 处理默认配置
|
||||||
|
for key, value in default_config.items():
|
||||||
|
if key.startswith("app."):
|
||||||
|
config_dict[key.replace("app.", "app_")] = value
|
||||||
|
elif key.startswith("server."):
|
||||||
|
config_dict[key.replace("server.", "")] = value
|
||||||
|
elif key == "env":
|
||||||
|
config_dict["env"] = value
|
||||||
|
|
||||||
|
# 5.2 处理环境特定配置
|
||||||
|
for key, value in env_config.items():
|
||||||
|
if key.startswith("server."):
|
||||||
|
config_dict[key.replace("server.", "")] = value
|
||||||
|
elif key == "debug":
|
||||||
|
config_dict["debug"] = value
|
||||||
|
|
||||||
|
# 5.3 处理 database 配置
|
||||||
|
database_config = {}
|
||||||
|
if "database" in env_config:
|
||||||
|
database_type = env_config["database"].get("type", "sqlite")
|
||||||
|
database_config = env_config["database"].get(database_type, {})
|
||||||
|
config_dict["database_type"] = database_type
|
||||||
|
# 5.4 处理 generate_schemas
|
||||||
|
if "database" in env_config:
|
||||||
|
db_config = env_config["database"]
|
||||||
|
if isinstance(db_config, dict) and "generate_schemas" in db_config:
|
||||||
|
config_dict["generate_schemas"] = db_config["generate_schemas"]
|
||||||
|
|
||||||
|
if database_type == "sqlite":
|
||||||
|
if database_config:
|
||||||
|
config_dict["sqlite_config"] = SQLiteConfig(**database_config)
|
||||||
|
|
||||||
|
return cls(**config_dict)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ 加载配置失败: {e}")
|
print(f"❌ 加载配置失败: {e}")
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return cls()
|
return cls()
|
||||||
|
|
||||||
|
|
||||||
# 全局配置实例
|
# 全局配置实例
|
||||||
_settings = None
|
_settings = None
|
||||||
|
|
||||||
|
|
||||||
def get_settings() -> Settings:
|
def get_settings() -> Settings:
|
||||||
"""获取配置实例(单例模式)"""
|
"""获取配置实例(单例模式)"""
|
||||||
global _settings
|
global _settings
|
||||||
if _settings is None:
|
if _settings is None:
|
||||||
_settings = Settings.from_toml(args.config)
|
_settings = Settings.from_toml(args.config)
|
||||||
return _settings
|
return _settings
|
||||||
|
|||||||
+26
-23
@@ -1,19 +1,21 @@
|
|||||||
"""
|
"""
|
||||||
Tortoise-ORM 数据库配置
|
Tortoise-ORM 数据库配置
|
||||||
"""
|
"""
|
||||||
from typing import Optional
|
|
||||||
from tortoise import Tortoise
|
from tortoise import Tortoise
|
||||||
from tortoise.contrib.fastapi import register_tortoise
|
from tortoise.contrib.fastapi import register_tortoise
|
||||||
from .config import get_settings
|
from .config import get_settings
|
||||||
|
|
||||||
|
|
||||||
|
settings = get_settings()
|
||||||
|
|
||||||
|
|
||||||
async def init_db(run_mode: str):
|
async def init_db(run_mode: str):
|
||||||
"""初始化数据库连接"""
|
"""初始化数据库连接"""
|
||||||
settings = get_settings()
|
db_config = getattr(settings, f"{settings.database_type}_config").tortoise_config
|
||||||
if run_mode == "production":
|
if run_mode == "production":
|
||||||
db_config = {
|
db_config = {
|
||||||
"connections": {
|
"connections": db_config,
|
||||||
"default": settings.database_url
|
|
||||||
},
|
|
||||||
"apps": {
|
"apps": {
|
||||||
"models": {
|
"models": {
|
||||||
"models": ["app.models", "aerich.models"],
|
"models": ["app.models", "aerich.models"],
|
||||||
@@ -23,11 +25,10 @@ async def init_db(run_mode: str):
|
|||||||
"use_tz": False,
|
"use_tz": False,
|
||||||
"timezone": "UTC",
|
"timezone": "UTC",
|
||||||
}
|
}
|
||||||
|
|
||||||
elif run_mode == "development":
|
elif run_mode == "development":
|
||||||
db_config = {
|
db_config = {
|
||||||
"connections": {
|
"connections": db_config,
|
||||||
"default": settings.database_url
|
|
||||||
},
|
|
||||||
"apps": {
|
"apps": {
|
||||||
"models": {
|
"models": {
|
||||||
"models": ["{{ cookiecutter.project_name }}.app.models", "aerich.models"],
|
"models": ["{{ cookiecutter.project_name }}.app.models", "aerich.models"],
|
||||||
@@ -39,9 +40,9 @@ async def init_db(run_mode: str):
|
|||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid run mode")
|
raise ValueError("Invalid run mode")
|
||||||
|
|
||||||
await Tortoise.init(db_config)
|
await Tortoise.init(db_config)
|
||||||
|
|
||||||
# 根据配置决定是否生成表结构
|
# 根据配置决定是否生成表结构
|
||||||
if settings.generate_schemas:
|
if settings.generate_schemas:
|
||||||
print("🗃️ 生成数据库表结构...")
|
print("🗃️ 生成数据库表结构...")
|
||||||
@@ -49,41 +50,44 @@ async def init_db(run_mode: str):
|
|||||||
print("✅ 数据库表结构生成完成")
|
print("✅ 数据库表结构生成完成")
|
||||||
else:
|
else:
|
||||||
print("⏭️ 跳过数据库表结构生成(建议使用迁移工具)")
|
print("⏭️ 跳过数据库表结构生成(建议使用迁移工具)")
|
||||||
|
|
||||||
print(f"✅ 数据库连接成功: {settings.database_url}")
|
print(f"✅ 数据库连接成功: {db_config}")
|
||||||
|
|
||||||
|
|
||||||
async def close_db():
|
async def close_db():
|
||||||
"""关闭数据库连接"""
|
"""关闭数据库连接"""
|
||||||
await Tortoise.close_connections()
|
await Tortoise.close_connections()
|
||||||
print("✅ 数据库连接已关闭")
|
print("✅ 数据库连接已关闭")
|
||||||
|
|
||||||
|
|
||||||
def register_db(app, run_mode: str):
|
def register_db(app, run_mode: str):
|
||||||
"""将数据库注册到 FastAPI 应用"""
|
"""将数据库注册到 FastAPI 应用"""
|
||||||
settings = get_settings()
|
|
||||||
|
|
||||||
modules_path = "app.models" if run_mode == "production" else "{{ cookiecutter.project_name }}.app.models"
|
|
||||||
|
|
||||||
|
modules_path = "app.models" if run_mode == "production" else "{{ cookiecutter.project_name }}.app.models"
|
||||||
|
file_path = getattr(settings, f"{settings.database_type}_config").file_path
|
||||||
register_tortoise(
|
register_tortoise(
|
||||||
app,
|
app,
|
||||||
db_url=settings.database_url,
|
db_url=f"sqlite://{file_path}",
|
||||||
modules={"models": [modules_path]},
|
modules={"models": [modules_path]},
|
||||||
generate_schemas=settings.generate_schemas,
|
generate_schemas=settings.generate_schemas,
|
||||||
add_exception_handlers=True,
|
add_exception_handlers=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
# 在 app/core/database.py 中添加
|
# 在 app/core/database.py 中添加
|
||||||
from aerich import Command
|
from aerich import Command
|
||||||
|
|
||||||
|
|
||||||
async def run_migrations():
|
async def run_migrations():
|
||||||
"""运行数据库迁移"""
|
"""运行数据库迁移"""
|
||||||
try:
|
try:
|
||||||
command = Command(
|
command = Command(
|
||||||
tortoise_config={
|
tortoise_config={
|
||||||
"connections": {
|
"connections": getattr(
|
||||||
"default": get_settings().database_url
|
settings, f"{settings.database_type}_config"
|
||||||
},
|
).tortoise_config,
|
||||||
"apps": {
|
"apps": {
|
||||||
"models": {
|
"models": {
|
||||||
"models": ["app.models", "aerich.models"],
|
"models": ["app.models", "aerich.models"],
|
||||||
@@ -91,13 +95,12 @@ async def run_migrations():
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
app="models"
|
app="models",
|
||||||
)
|
)
|
||||||
|
|
||||||
# 检查并应用迁移
|
# 检查并应用迁移
|
||||||
await command.init()
|
await command.init()
|
||||||
await command.upgrade()
|
await command.upgrade()
|
||||||
print("✅ 数据库迁移完成")
|
print("✅ 数据库迁移完成")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ 数据库迁移失败: {e}")
|
print(f"⚠️ 数据库迁移失败: {e}")
|
||||||
|
|
||||||
Reference in New Issue
Block a user