Compare commits

...

6 Commits

Author SHA1 Message Date
Misaka_Company
fb759ebe33 docs: update README with YAML configuration instructions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-12 09:47:10 +08:00
Misaka_Company
b9e13105e1 chore: ignore local YAML config overrides
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-12 09:45:06 +08:00
Misaka_Company
70cb6759ea refactor: remove old .env and config.py files
Remove deprecated app/core/config.py as configuration is now managed
through the new YAML-based config module (app/config/).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-12 09:44:03 +08:00
Misaka_Company
f94a18fee7 feat: add config error handling on startup
Add error handling for configuration loading at application startup.
If the config file is missing or invalid, the app will exit with
a clear error message instead of crashing later.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-12 09:42:45 +08:00
Misaka_Company
a6873ae2ee fix: resolve YAML config path relative to project root
Ensure config/settings.yaml can be found when running from any working
directory by resolving the path relative to the settings.py file location
rather than the current working directory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-12 09:40:46 +08:00
Misaka_Company
8292de7747 refactor: update database.py to use new config module
Update import statement from app.core.config to config.settings as part
of YAML configuration migration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-12 09:37:52 +08:00
6 changed files with 46 additions and 34 deletions

5
.gitignore vendored
View File

@@ -6,4 +6,7 @@ __pycache__/
dist/ dist/
build/ build/
.pytest_cache/ .pytest_cache/
.claude/ .claude/
# Local configuration overrides
config/settings.local.yaml

View File

@@ -11,3 +11,25 @@ source .venv/bin/activate # Linux/Mac
pip install -r requirements.txt pip install -r requirements.txt
uvicorn app.main:app --reload uvicorn app.main:app --reload
``` ```
## Configuration
Configuration is managed via YAML files in the `config/` directory.
### Configuration File
Edit `config/settings.yaml` to configure your environment:
```yaml
database:
sql_server:
host: your-host
port: 1433
database: your-database
username: your-username
password: your-password
```
### Local Overrides
For local development, create `config/settings.local.yaml` to override specific values without committing them.

View File

@@ -1,32 +0,0 @@
from sqlalchemy.engine import URL
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
SQL_SERVER_HOST: str
SQL_SERVER_PORT: int = 1433
SQL_SERVER_DATABASE: str
SQL_SERVER_USERNAME: str
SQL_SERVER_PASSWORD: str
SQL_SERVER_DRIVER: str = "{ODBC Driver 18 for SQL Server}"
SQL_SERVER_TRUST_SERVER_CERTIFICATE: str = "yes"
@property
def database_url(self) -> URL:
return URL.create(
"mssql+pyodbc",
username=self.SQL_SERVER_USERNAME,
password=self.SQL_SERVER_PASSWORD,
host=self.SQL_SERVER_HOST,
port=self.SQL_SERVER_PORT,
database=self.SQL_SERVER_DATABASE,
query={
"driver": self.SQL_SERVER_DRIVER.strip("{}"),
"TrustServerCertificate": self.SQL_SERVER_TRUST_SERVER_CERTIFICATE,
},
)
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
settings = Settings()

View File

@@ -3,7 +3,7 @@ from typing import Generator
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker
from app.core.config import settings from config.settings import settings
engine = create_engine( engine = create_engine(
settings.database_url, settings.database_url,

View File

@@ -1,7 +1,21 @@
import sys
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from config.settings import load_settings
# 加载配置文件,失败则退出
try:
settings = load_settings()
except FileNotFoundError as e:
print(f"配置文件错误: {e}")
sys.exit(1)
except Exception as e:
print(f"加载配置失败: {e}")
sys.exit(1)
from app.api.v1.location import router as location_router from app.api.v1.location import router as location_router
from app.api.v1.box import router as box_router from app.api.v1.box import router as box_router
from app.services.location_service import DuplicateLocationError from app.services.location_service import DuplicateLocationError

View File

@@ -45,7 +45,12 @@ class Settings(BaseModel):
def load_settings(config_path: str = "config/settings.yaml") -> Settings: def load_settings(config_path: str = "config/settings.yaml") -> Settings:
"""加载 YAML 配置文件""" """加载 YAML 配置文件"""
# Resolve relative to the project root (where config/ directory exists)
path = Path(config_path) path = Path(config_path)
if not path.is_absolute():
# __file__ is config/settings.py, so parent.parent gives us project root
project_root = Path(__file__).resolve().parent.parent
path = project_root / config_path
if not path.exists(): if not path.exists():
raise FileNotFoundError( raise FileNotFoundError(
f"配置文件不存在: {config_path}\n" f"配置文件不存在: {config_path}\n"