ShiErFeng/shierfeng-fastapi-backend/config/database.py
2026-07-24 09:43:10 +08:00

110 lines
3.5 KiB
Python

from urllib.parse import quote_plus
from sqlalchemy import Engine, create_engine
from sqlalchemy.ext.asyncio import AsyncAttrs, AsyncEngine, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase, sessionmaker
from config.env import DataBaseConfig
def build_async_sqlalchemy_database_url() -> str:
"""
构建异步 SQLAlchemy 数据库连接 URL
:return: 异步 SQLAlchemy 数据库连接 URL
"""
if DataBaseConfig.db_type == 'postgresql':
return (
f'postgresql+asyncpg://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
return (
f'mysql+asyncmy://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
ASYNC_SQLALCHEMY_DATABASE_URL = build_async_sqlalchemy_database_url()
def build_sync_sqlalchemy_database_url() -> str:
"""
构建同步 SQLAlchemy 数据库连接 URL
:return: 同步 SQLAlchemy 数据库连接 URL
"""
if DataBaseConfig.db_type == 'postgresql':
return (
f'postgresql+psycopg2://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
return (
f'mysql+pymysql://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
SYNC_SQLALCHEMY_DATABASE_URL = build_sync_sqlalchemy_database_url()
def create_async_db_engine(echo: bool | None = None) -> AsyncEngine:
"""
创建异步 SQLAlchemy Engine
:param echo: 可选,是否输出 SQLAlchemy SQL 日志
:return: 异步 SQLAlchemy Engine
"""
return create_async_engine(
ASYNC_SQLALCHEMY_DATABASE_URL,
echo=DataBaseConfig.db_echo if echo is None else echo,
max_overflow=DataBaseConfig.db_max_overflow,
pool_size=DataBaseConfig.db_pool_size,
pool_recycle=DataBaseConfig.db_pool_recycle,
pool_timeout=DataBaseConfig.db_pool_timeout,
)
def create_sync_db_engine(echo: bool | None = None) -> Engine:
"""
创建同步 SQLAlchemy Engine
:param echo: 可选,是否输出 SQLAlchemy SQL 日志
:return: 同步 SQLAlchemy Engine
"""
return create_engine(
SYNC_SQLALCHEMY_DATABASE_URL,
echo=DataBaseConfig.db_echo if echo is None else echo,
max_overflow=DataBaseConfig.db_max_overflow,
pool_size=DataBaseConfig.db_pool_size,
pool_recycle=DataBaseConfig.db_pool_recycle,
pool_timeout=DataBaseConfig.db_pool_timeout,
)
def create_async_session_local(engine: AsyncEngine) -> async_sessionmaker:
"""
创建异步 Session 工厂
:param engine: 异步 SQLAlchemy Engine
:return: 异步 Session 工厂
"""
return async_sessionmaker(autocommit=False, autoflush=False, bind=engine)
def create_sync_session_local(engine: Engine) -> sessionmaker:
"""
创建同步 Session 工厂
:param engine: 同步 SQLAlchemy Engine
:return: 同步 Session 工厂
"""
return sessionmaker(autocommit=False, autoflush=False, bind=engine)
async_engine = create_async_db_engine()
AsyncSessionLocal = create_async_session_local(async_engine)
class Base(AsyncAttrs, DeclarativeBase):
pass