feat: schema.py (DDL 5 таблиц), db.py без DDL, app.py минимальный, test_routes с комментариями
По рекомендации Sonnet: - schema.py — все DDL (documents, contracts, supplements, spec_rows, spec_history) - db.py — только транспорт (connect/query), DDL убран - app.py — минимальный: ensure_schema() + register_blueprint() - test_routes.py — подробные комментарии, исправлен импорт psysql
This commit is contained in:
+28
-25
@@ -1,10 +1,26 @@
|
||||
"""
|
||||
db.py — Транспортный слой к базе данных.
|
||||
|
||||
Только connect() и query(). Никакой бизнес-логики, никакого DDL.
|
||||
DDL → schema.py. Бизнес-запросы → upload.py, extractor.py, api.py.
|
||||
|
||||
Функции:
|
||||
_pg_connect(dbname) — сырое подключение к ЛЮБОЙ базе (используется /test createdb)
|
||||
connect() — подключение к ЦЕЛЕВОЙ базе (из DB_NAME)
|
||||
query(sql, params) — выполнить запрос → (result, error)
|
||||
"""
|
||||
|
||||
import os
|
||||
import psycopg2
|
||||
from psycopg2 import sql
|
||||
|
||||
|
||||
def _pg_connect(dbname):
|
||||
"""Сырое подключение к указанной базе."""
|
||||
"""
|
||||
Сырое подключение к указанной базе данных.
|
||||
Используется:
|
||||
- connect() для целевой БД
|
||||
- test_routes.py для /test createdb (подключение к 'postgres')
|
||||
"""
|
||||
return psycopg2.connect(
|
||||
host=os.getenv("DB_HOST"),
|
||||
port=os.getenv("DB_PORT", 5432),
|
||||
@@ -16,36 +32,23 @@ def _pg_connect(dbname):
|
||||
|
||||
|
||||
def connect():
|
||||
"""Подключение к целевой БД. Возвращает (connection, None) или (None, error)."""
|
||||
"""
|
||||
Подключение к ЦЕЛЕВОЙ базе данных (DB_NAME из переменных окружения).
|
||||
Возвращает (connection, None) при успехе или (None, error) при ошибке.
|
||||
"""
|
||||
try:
|
||||
return _pg_connect(os.getenv("DB_NAME")), None
|
||||
except Exception as e:
|
||||
return None, str(e)
|
||||
|
||||
|
||||
def ensure_db():
|
||||
"""Создать базу, если не существует."""
|
||||
db_name = os.getenv("DB_NAME", "contracts")
|
||||
try:
|
||||
conn = _pg_connect("postgres")
|
||||
conn.autocommit = True
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT 1 FROM pg_database WHERE datname = %s", (db_name,))
|
||||
if cur.fetchone():
|
||||
print(f"DB '{db_name}' exists")
|
||||
else:
|
||||
cur.execute(sql.SQL("CREATE DATABASE {}").format(sql.Identifier(db_name)))
|
||||
print(f"DB '{db_name}' created")
|
||||
cur.close()
|
||||
conn.close()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"ensure_db error: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def query(sql_text, params=None):
|
||||
"""Выполнить запрос, вернуть (result, error)."""
|
||||
"""
|
||||
Выполнить SQL-запрос к целевой БД.
|
||||
Возвращает (result, None) или (None, error).
|
||||
|
||||
result = {"columns": [...], "rows": [[...], ...]}
|
||||
"""
|
||||
conn, err = connect()
|
||||
if err:
|
||||
return None, f"connect: {err}"
|
||||
|
||||
Reference in New Issue
Block a user