项目模板

作者:xiongfanyi 发布时间: 2025-10-29 阅读量:11 评论数:0

项目模板

fastapi

1、初始化项目

#!/bin/bash
# fastapi 项目初始化

# 初始化目录结构
mkdir -pv ./{core,common,service,repo,scheme,utils,api/v1,db,etc,model}

# 增加日志
cat > core/logging.py <<'EOF'
import logging
import os,sys
from datetime import datetime
from etc.config import settings
from logging.handlers import RotatingFileHandler

# 创建日志目录
LOG_DIR = os.environ.get("LOG_DIR", settings.LOG_DIR)
if not os.path.exists(LOG_DIR): os.makedirs(LOG_DIR)


# 业务日志
BIZ_LOG_FILE_NAME = f"biz{datetime.now().strftime('%Y%m%d')}.log"
# 系统日志
SYS_LOG_FILE_NAME = f"sys{datetime.now().strftime('%Y%m%d')}.log"

# 文件路径
BIZ_LOG_FILE = os.path.join(LOG_DIR, BIZ_LOG_FILE_NAME)
SYS_LOG_FILE = os.path.join(LOG_DIR, SYS_LOG_FILE_NAME)

# 日志格式
BUSINESS_LOG_FORMAT = "[%(asctime)s] [%(name)s] [%(levelname)s] [%(filename)s:%(funcName)s:%(lineno)d] %(message)s"
SYSTEM_LOG_FORMAT = "[%(asctime)s] [%(name)s] [%(levelname)s] [%(filename)s:%(funcName)s:%(lineno)d] %(message)s"

# 业务日志
def setup_business_logger():
    # 禁用 Uvicorn 访问日志
    logging.getLogger("uvicorn.access").setLevel(logging.CRITICAL)
    logger = logging.getLogger("BIZ")
    logger.setLevel(logging.INFO)  # 业务日志一般从 INFO 开始

    # 文件 Handler(带轮转:最多10MB,保留5个旧文件)
    file_handler = RotatingFileHandler(
        BIZ_LOG_FILE, maxBytes=200 * 1024 * 1024, backupCount=5, encoding="utf-8"
    )
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(logging.Formatter(BUSINESS_LOG_FORMAT))


    # 日志输出到控制台
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setLevel(logging.INFO)
    console_handler.setFormatter(logging.Formatter(BUSINESS_LOG_FORMAT))

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)
    return logger

# 系统日志
def setup_system_logger():
    logger = logging.getLogger("SYS")
    logger.setLevel(logging.DEBUG)  # 系统日志可能需要更多调试信息

    # 日志输出到控制台
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setLevel(logging.DEBUG)
    # 文件 Handler(带轮转:最多10MB,保留5个旧文件)
    file_handler = RotatingFileHandler(
        SYS_LOG_FILE, maxBytes=200 * 1024 * 1024, backupCount=5, encoding="utf-8"
    )
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(logging.Formatter(SYSTEM_LOG_FORMAT))    
    console_handler.setFormatter(logging.Formatter(SYSTEM_LOG_FORMAT))

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)
    return logger

# 初始化日志
biz_log = setup_business_logger()
sys_log = setup_system_logger()
EOF

# 增加配置文件
cat > etc/config.py <<'EOF'
from pydantic_settings import BaseSettings
from pydantic import SecretStr, Field
from pathlib import Path


class Config(BaseSettings):
  # 服务监听端口
  SERVER_PORT: int = Field(..., env="SERVER_PORT")

  # 日志路径
  LOG_DIR: str = Field(..., env="LOG_DIR")

  class Config:
      env_file = ".env"

settings = Config()
EOF

# 增加默认环境变量
cat > .env <<'EOF'
# 服务监听端口
SERVER_PORT=9090
# 日志路径
LOG_DIR=/tmp
EOF

# 增加路由规则
cat > api/__init__.py <<'EOF'
# -*- coding:utf-8 -*-
from fastapi import APIRouter
v1_api_router = APIRouter(prefix="/api/v1")
EOF

# 增加数据库脚本
cat > db/database.py <<'EOF'
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from etc.config import settings
from core.logging import biz_log,sys_log

#DATABASE_URL = f"mysql+pymysql://{settings.DB_USERNAME}:{settings.DB_PASSWORD}@{settings.DB_HOSTS}:{settings.DB_PORT}/{settings.DB_DATABASE}?charset=utf8mb4"
DATABASE_URL="sqlite:///./test.db"
sys_log.info(f"数据库连接信息: {DATABASE_URL}")

# 创建 SQLAlchemy 引擎
engine = create_engine(
    DATABASE_URL,
    pool_pre_ping=True
    )

# 创建 session 工厂
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# 声明模型基类
Base = declarative_base()

# 统一设置字符集
class BaseModel(Base):
    __abstract__ = True
    
    # 为所有表设置统一的字符集和排序规则
    __table_args__ = {
        'mysql_engine': 'InnoDB',
        'mysql_charset': 'utf8mb4',
        'mysql_collate': 'utf8mb4_unicode_ci'
    }
EOF

cat > db/init_db.py <<'EOF'
from db.database import Base, engine # 导入共享的 Base 和 engine
from core.logging import sys_log

# ----------------------------------------------------
# 导入所有模型文件,让 SQLAlchemy 认识它们!
# ----------------------------------------------------
# import model.book.model_book
# ... 导入您的其他模型文件

def initialize_database():
    """
    负责创建数据库文件和所有表结构。
    """
    sys_log.info("正在检查并创建数据库表结构...")
    # Base.metadata 现在包含了上面所有导入的模型信息
    Base.metadata.create_all(bind=engine)
    sys_log.info("数据库表结构检查完成.")
EOF

# 生成 .gitignore
cat >.gitignore <<'EOF'
# ----------------------------------------------------
# 1. 虚拟环境和编译文件 (Python Standard)
# ----------------------------------------------------
# 虚拟环境目录
venv/
.venv/
env/
.Python

# Python 编译和缓存文件
__pycache__/
*.pyc
*.pyo
*~
*.swp

# ----------------------------------------------------
# 2. IDE 和操作系统文件
# ----------------------------------------------------
.DS_Store    # macOS
.vscode      # Visual Studio Code 缓存和本地配置
.idea/       # PyCharm/IntelliJ 配置文件
Thumbs.db    # Windows

# ----------------------------------------------------
# 3. 敏感配置和数据库
# ----------------------------------------------------
# 【关键】包含数据库密码和 API 密钥的配置文件
.env
.flaskenv

# 本地 SQLite/测试数据库文件
*.sqlite3
*.db
sql_app.db
test.db

# ----------------------------------------------------
# 4. 测试和文档生成文件
# ----------------------------------------------------
.pytest_cache/  # pytest 缓存
.coverage       # coverage 报告
htmlcov/
docs/_build/    # Sphinx 文档生成目录

# ----------------------------------------------------
# 5. 打包和部署文件
# ----------------------------------------------------
# Docker 构建缓存和忽略文件
.dockerignore
build/
dist/
EOF

# 增加启动脚本
cat > main.py <<'EOF'
# app/main.py
import uvicorn
from fastapi import FastAPI
from api import v1_api_router
from core.logging import biz_log,sys_log
from etc.config import settings
from starlette.middleware.cors import CORSMiddleware
from db.database import Base, engine

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 创建库表结构
Base.metadata.create_all(bind=engine)

# 注册路由
app.include_router(v1_api_router)

@app.get("/")
def read_root():
    biz_log.error("Root endpoint called")
    return {"message": "Welcome to FastAPI!"}

def main():
    sys_log.info(f"服务启动在端口 {settings.SERVER_PORT}")

    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=settings.SERVER_PORT,
        workers=1,
        reload=True,
        log_config=None
    )


if __name__ == "__main__":
    main()
EOF

评论