Python后端标准分包思想(完整版下)
7. common(公共模块层,全名:common/core)
核心职责:存放项目全局共用的配置、常量、异常、类,贯穿整个项目。
核心内容:
-
全局常量(如状态码、宠物领养状态、权限标识)
-
枚举类(如GenderEnum、AdoptStatusEnum、ErrorCodeEnum)
-
公共异常类(如CustomException、ParamsError、BusinessError)
-
公共返回格式(统一响应体,如{"code":200,"msg":"success","data":{}})
-
全局中间件(如日志中间件、跨域中间件、权限中间件)
-
全局依赖(如登录校验依赖、数据库会话依赖)
关键特点:项目内全局复用,与业务相关但不包含具体业务逻辑。
7.1 统一响应格式
# common/response.py - 统一响应格式
from typing import Any, Optional
def success_response(
data: Any = None,
message: str = "success",
code: int = 200
) -> dict:
"""成功响应"""
return {
"code": code,
"message": message,
"data": data
}
def error_response(
message: str = "error",
code: int = 400,
data: Any = None
) -> dict:
"""失败响应"""
return {
"code": code,
"message": message,
"data": data
}
# 通用分页响应包装
def page_response(items: list, total: int, page: int, page_size: int) -> dict:
return {
"items": items,
"total": total,
"page": page,
"page_size": page_size,
"total_pages": (total + page_size - 1) // page_size
}
7.2 自定义异常
# common/exceptions.py - 自定义异常
class BusinessException(Exception):
"""业务异常"""
def __init__(self, message: str, code: int = 400):
self.code = code
self.message = message
super().__init__(self.message)
class NotFoundException(BusinessException):
"""资源不存在异常"""
def __init__(self, message: str = "资源不存在"):
super().__init__(message, code=404)
class PermissionDeniedException(BusinessException):
"""权限不足异常"""
def __init__(self, message: str = "权限不足"):
super().__init__(message, code=403)
class ValidationException(BusinessException):
"""数据校验异常"""
def __init__(self, message: str = "数据校验失败"):
super().__init__(message, code=422)
7.3 全局常量
# common/constants.py - 全局常量
# 状态码常量
class StatusCode:
SUCCESS = 200
BAD_REQUEST = 400
UNAUTHORIZED = 401
FORBIDDEN = 403
NOT_FOUND = 404
INTERNAL_ERROR = 500
# 业务常量
ADOPT_STATUS = {
"pending": "待审核",
"approved": "已批准",
"rejected": "已拒绝",
"completed": "已完成"
}
PET_SPECIES = ["狗", "猫", "兔子", "仓鼠", "鸟"]
# 权限标识
PERMISSIONS = {
"admin": ["pet:create", "pet:update", "pet:delete", "user:list"],
"user": ["pet:list", "pet:view", "adopt:create"]
}
7.4 枚举类
# common/enums.py - 枚举类
from enum import Enum
class GenderEnum(str, Enum):
MALE = "male"
FEMALE = "female"
OTHER = "other"
class AdoptStatusEnum(str, Enum):
PENDING = "pending"
APPROVED = "approved"
REJECTED = "rejected"
COMPLETED = "completed"
class RoleEnum(str, Enum):
ADMIN = "admin"
USER = "user"
GUEST = "guest"
7.5 全局yi
# common/dependencies.py - 全局依赖
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from database import get_db
from utils.jwt_utils import decode_token
from common.exceptions import PermissionDeniedException
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db)
):
"""获取当前登录用户(依赖注入)"""
token = credentials.credentials
try:
payload = decode_token(token)
user_id = payload.get("user_id")
if not user_id:
raise HTTPException(status_code=401, detail="无效的token")
# 从数据库查询用户(避免重复查询可以缓存)
from crud.user_crud import UserCRUD
user_crud = UserCRUD(db)
user = user_crud.get_by_id(user_id)
if not user:
raise HTTPException(status_code=401, detail="用户不存在")
return user
except Exception as e:
raise HTTPException(status_code=401, detail=str(e))
def require_admin(current_user: dict = Depends(get_current_user)):
"""要求管理员权限"""
if current_user.get('role') != 'admin':
raise PermissionDeniedException("需要管理员权限")
return current_user
8. database.py(数据库连接层)
核心职责:负责数据库的连接配置,提供数据库会话。
核心内容:
-
数据库引擎配置(连接地址、用户名、密码、端口)
-
数据库会话创建(SessionLocal)
-
数据库迁移相关配置(如alembic关联)
-
# database.py from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, Session from typing import Generator from settings import settings # 创建数据库引擎 # SQLite示例(开发环境) # engine = create_engine( # "sqlite:///./pet_adopt.db", # connect_args={"check_same_thread": False}, # echo=True # ) # MySQL示例(生产环境) engine = create_engine( settings.DATABASE_URL, pool_pre_ping=True, # 连接前检查是否有效 pool_recycle=3600, # 1小时回收连接 echo=settings.DEBUG # 开发环境打印SQL ) # 创建会话工厂 SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) # 创建基类(供models继承) Base = declarative_base() def get_db() -> Generator[Session, None, None]: """ 获取数据库会话(依赖注入用) 使用方式:db: Session = Depends(get_db) """ db = SessionLocal() try: yield db finally: db.close() # 初始化数据库(创建所有表) def init_db(): Base.metadata.create_all(bind=engine)
9. settings.py(全局配置层)
核心职责:存放项目全局配置,统一管理环境变量、服务配置。
核心内容:
-
服务配置(端口、主机、调试模式)
-
环境变量(开发/测试/生产环境区分)
-
第三方服务配置(如短信API密钥、OSS配置)
-
密钥配置(如JWT密钥、加密密钥)
# settings.py
from pydantic_settings import BaseSettings
from typing import Optional
import os
from dotenv import load_dotenv
load_dotenv() # 加载.env文件
class Settings(BaseSettings):
"""应用配置"""
# 基础配置
APP_NAME: str = "宠物领养系统"
DEBUG: bool = os.getenv("DEBUG", "True").lower() == "true"
HOST: str = os.getenv("HOST", "0.0.0.0")
PORT: int = int(os.getenv("PORT", "8000"))
# 数据库配置
# SQLite
# DATABASE_URL: str = "sqlite:///./pet_adopt.db"
# MySQL
DB_HOST: str = os.getenv("DB_HOST", "localhost")
DB_PORT: int = int(os.getenv("DB_PORT", "3306"))
DB_USER: str = os.getenv("DB_USER", "root")
DB_PASSWORD: str = os.getenv("DB_PASSWORD", "123456")
DB_NAME: str = os.getenv("DB_NAME", "pet_adopt")
@property
def DATABASE_URL(self) -> str:
"""动态构建数据库连接字符串"""
return f"mysql+pymysql://{self.DB_USER}:{self.DB_PASSWORD}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}?charset=utf8mb4"
# JWT配置
JWT_SECRET_KEY: str = os.getenv("JWT_SECRET_KEY", "your-secret-key-change-in-production")
JWT_ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
REFRESH_TOKEN_EXPIRE_DAYS: int = 7
# 第三方服务配置
SMS_API_KEY: Optional[str] = os.getenv("SMS_API_KEY")
SMS_API_SECRET: Optional[str] = os.getenv("SMS_API_SECRET")
OSS_ACCESS_KEY: Optional[str] = os.getenv("OSS_ACCESS_KEY")
OSS_SECRET_KEY: Optional[str] = os.getenv("OSS_SECRET_KEY")
OSS_BUCKET_NAME: Optional[str] = os.getenv("OSS_BUCKET_NAME")
OSS_ENDPOINT: Optional[str] = os.getenv("OSS_ENDPOINT")
# Redis配置
REDIS_HOST: str = os.getenv("REDIS_HOST", "localhost")
REDIS_PORT: int = int(os.getenv("REDIS_PORT", "6379"))
REDIS_DB: int = int(os.getenv("REDIS_DB", "0"))
REDIS_PASSWORD: Optional[str] = os.getenv("REDIS_PASSWORD")
class Config:
env_file = ".env"
case_sensitive = True
# 创建全局配置实例
settings = Settings()
.env文件示例
# .env
DEBUG=True
HOST=0.0.0.0
PORT=8000
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=123456
DB_NAME=pet_adopt
JWT_SECRET_KEY=your-super-secret-key-please-change
SMS_API_KEY=your-sms-api-key
10. main.py(项目入口)
核心职责:启动FastAPI服务,注册路由、中间件、依赖等。
核心内容:
-
创建FastAPI实例
-
注册controllers层的路由
-
加载中间件、全局依赖
-
启动服务(if __name__ == "__main__";: uvicorn.run())
# main.py
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
import uvicorn
from datetime import datetime
from settings import settings
from database import init_db, get_db
from common.response import error_response
from common.exceptions import BusinessException
# 导入所有路由
from controllers.pet_controller import router as pet_router
# from controllers.user_controller import router as user_router
# from controllers.adopt_controller import router as adopt_router
# 创建FastAPI应用实例
app = FastAPI(
title=settings.APP_NAME,
description="宠物领养系统API文档",
version="1.0.0",
docs_url="/docs" if settings.DEBUG else None, # 生产环境可关闭
redoc_url="/redoc" if settings.DEBUG else None
)
# ========== 配置中间件 ==========
# 1. CORS跨域中间件(允许前端调用)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"] if settings.DEBUG else ["https://your-domain.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 2. 信任主机中间件(安全)
if not settings.DEBUG:
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["your-domain.com", "api.your-domain.com"]
)
# 3. 自定义请求日志中间件
@app.middleware("http")
async def log_requests(request: Request, call_next):
"""记录所有请求日志"""
start_time = datetime.now()
# 记录请求信息
print(f"[{start_time}] {request.method} {request.url.path}")
# 处理请求
response = await call_next(request)
# 计算耗时
process_time = (datetime.now() - start_time).total_seconds()
response.headers["X-Process-Time"] = str(process_time)
print(f"[{datetime.now()}] 完成 {request.method} {request.url.path} - 耗时: {process_time:.3f}s")
return response
# ========== 全局异常处理 ==========
@app.exception_handler(BusinessException)
async def business_exception_handler(request: Request, exc: BusinessException):
"""业务异常统一处理"""
return error_response(
message=exc.message,
code=exc.code
)
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
"""全局异常兜底"""
print(f"未处理的异常: {exc}")
return error_response(
message="服务器内部错误",
code=500
)
# ========== 注册路由 ==========
app.include_router(pet_router)
# app.include_router(user_router, prefix="/api")
# app.include_router(adopt_router, prefix="/api")
# ========== 健康检查接口 ==========
@app.get("/health", tags=["系统"])
async def health_check():
"""健康检查接口"""
return {
"status": "healthy",
"service": settings.APP_NAME,
"timestamp": datetime.now().isoformat()
}
@app.get("/", tags=["系统"])
async def root():
"""根路径"""
return {
"message": f"欢迎使用{settings.APP_NAME}API",
"docs": "/docs" if settings.DEBUG else None
}
# ========== 启动事件 ==========
@app.on_event("startup")
async def startup_event():
"""应用启动时执行"""
print(f"正在启动{settings.APP_NAME}...")
# 初始化数据库表
init_db()
print(f"数据库连接成功")
print(f"API文档地址: http://{settings.HOST}:{settings.PORT}/docs")
print(f"服务已启动在: http://{settings.HOST}:{settings.PORT}")
@app.on_event("shutdown")
async def shutdown_event():
"""应用关闭时执行"""
print(f"{settings.APP_NAME}正在关闭...")
# ========== 启动服务 ==========
if __name__ == "__main__":
uvicorn.run(
"main:app",
host=settings.HOST,
port=settings.PORT,
reload=settings.DEBUG, # 开发模式自动重载
log_level="info"
)
三、核心调用关系(清晰易懂)
调用流程:前端 → 接口层 → 业务层 → 数据库操作层 → 数据库,schema、utils、common贯穿所有层。
前端请求 ↓ controllers(接收请求、校验参数) ↓ 调用 service(业务逻辑判断、流程控制) ↓ 调用 crud(基础数据库操作) ↓ 操作 models(表模型) ↓ 连接 database(数据库连接) 【辅助支撑】 schema:给controllers、service、crud提供数据结构和校验 utils:给所有层提供工具函数(如service调用密码加密、token生成) common:给所有层提供常量、异常、公共返回(如service抛出common定义的异常)
四、分包核心思想(为什么要这么分)
-
解耦:各层职责单一,修改某一层不影响其他层(如改数据库操作只动crud,改业务只动service)。
-
复用:utils工具函数、common公共配置可全局复用;crud、service可被多个controllers调用。
-
易维护:目录结构清晰,新人可快速定位“接口在哪、业务在哪、数据库操作在哪”。
-
易测试:每层独立,可单独做单元测试(如测试service不依赖controller,测试crud不依赖service)。
-
可扩展:后期新增功能(如新增“宠物寄养”接口),只需新增对应schema、controller、service、crud,不影响原有代码。
五、新手必踩坑(禁忌清单)
-
❌ 不分层:在controllers里直接写SQL、写业务逻辑(最常见错误)。
-
❌ 跳过service层:controllers直接调用crud(简单小项目可临时用,复杂项目必规范)。
-
❌ crud里写业务判断:如在crud的delete方法里判断“是否允许删除”(应放在service层)。
-
❌ utils里写业务逻辑:如在utils里写“宠物领养校验”(utils应与业务无关)。
-
❌ schema里写数据库操作:如在Pydantic模型里写查询方法(schema只负责数据结构)。
六、总结
Python后端标准分包思想的核心:每层只做自己分内的事,职责单一、层层解耦、全局复用。
记住一句话:schema管数据,controller管接口,service管业务,crud管数据库,utils管工具,common管公共,剩下的配置和入口负责串联整个项目。
这套架构适配所有Python后端项目(FastAPI、Flask),无论是小项目还是企业级项目,都能直接套用,是最规范、最通用的分包方式。
pet-adopt-system/
├── schemas/ # 数据模型层
│ ├── pet.py
│ └── user.py
├── controllers/ # 接口路由层
│ ├── pet_controller.py
│ └── user_controller.py
├── services/ # 业务逻辑层
│ ├── pet_service.py
│ └── user_service.py
├── crud/ # 数据库操作层
│ ├── pet_crud.py
│ └── user_crud.py
├── models/ # 数据库表模型
│ ├── pet.py
│ └── user.py
├── utils/ # 工具函数层
│ ├── jwt_utils.py
│ ├── password_utils.py
│ ├── date_utils.py
│ └── logger.py
├── common/ # 公共模块层
│ ├── response.py
│ ├── exceptions.py
│ ├── constants.py
│ ├── enums.py
│ └── dependencies.py
├── database.py # 数据库连接
├── settings.py # 全局配置
├── main.py # 项目入口
├── requirements.txt # 依赖包
└── .env # 环境变量
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)