Files
api-copp/route/init_data_base.py
2026-03-01 21:40:09 +05:00

108 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from fastapi import APIRouter, HTTPException
import pkgutil
import importlib
from pathlib import Path
from typing import List
from bd import Settings
from sqlalchemy import create_engine
from sqlalchemy.exc import SQLAlchemyError
from pydantic import BaseModel
router = APIRouter(tags=["db"])
def _iter_table_modules() -> List[str]:
try:
import bd.tables as tables_pkg
pkg_paths = getattr(tables_pkg, "__path__", None)
if not pkg_paths:
pkg_paths = [str(Path(__file__).resolve().parent.parent / "bd" / "tables")]
except Exception:
pkg_paths = [str(Path(__file__).resolve().parent.parent / "bd" / "tables")]
names = []
for finder, name, ispkg in pkgutil.iter_modules(pkg_paths):
names.append(name)
return names
def collect_metadatas():
metadatas = []
for mod_name in _iter_table_modules():
try:
module = importlib.import_module(f"bd.tables.{mod_name}")
except Exception:
continue
Base = getattr(module, "Base", None)
if Base is not None and hasattr(Base, "metadata"):
metadatas.append(Base.metadata)
return metadatas
@router.post("/db/create-tables")
async def create_tables():
"""Создаёт все таблицы, описанные в модулях `db.tables`.
Endpoint вызывается по нажатию кнопки в UI (POST).
"""
settings = Settings()
db_url = settings.DATABASE_URL_syncpg
engine = create_engine(db_url, future=True)
metadatas = collect_metadatas()
if not metadatas:
raise HTTPException(status_code=400, detail="No table metadata found in db.tables")
# deduplicate metadata objects (multiple modules may expose the same Base.metadata)
unique = []
seen = set()
for md in metadatas:
if id(md) not in seen:
seen.add(id(md))
unique.append(md)
try:
for md in unique:
md.create_all(bind=engine)
return {"status": "ok", "detail": f"Created {len(unique)} metadata groups"}
except SQLAlchemyError as e:
raise HTTPException(status_code=500, detail=str(e))
class ClearDBIn(BaseModel):
confirm: bool
@router.post("/db/clear")
async def clear_tables(payload: ClearDBIn):
"""Полная очистка всех таблиц, описанных в `bd.tables`.
Требуется явное подтверждение: POST с телом {"confirm": true}.
"""
if not payload.confirm:
raise HTTPException(status_code=400, detail="Confirmation required")
settings = Settings()
db_url = settings.DATABASE_URL_syncpg
engine = create_engine(db_url, future=True)
metadatas = collect_metadatas()
if not metadatas:
raise HTTPException(status_code=400, detail="No table metadata found in db.tables")
# deduplicate metadata objects
unique = []
seen = set()
for md in metadatas:
if id(md) not in seen:
seen.add(id(md))
unique.append(md)
try:
for md in unique:
md.drop_all(bind=engine)
return {"status": "ok", "detail": f"Dropped {len(unique)} metadata groups"}
except SQLAlchemyError as e:
raise HTTPException(status_code=500, detail=str(e))