From 240cd2ae83fa0624c087585711a037f5a0824bcc Mon Sep 17 00:00:00 2001 From: Lichun Date: Sun, 16 Nov 2025 01:12:02 +0000 Subject: [PATCH] database migration error fix --- py_backend/alembic/env.py | 25 +++++++++++++++++++++++-- py_backend/app/crud.py | 11 ++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/py_backend/alembic/env.py b/py_backend/alembic/env.py index 332eb8e0..2136667d 100644 --- a/py_backend/alembic/env.py +++ b/py_backend/alembic/env.py @@ -27,10 +27,31 @@ def _get_db_url() -> str: url = os.getenv("ALEMBIC_DATABASE_URL") or os.getenv("DATABASE_URL") if not url: - raise RuntimeError("Set ALEMBIC_DATABASE_URL or DATABASE_URL for Alembic migrations.") + # Try to get it from app.config.settings as fallback + try: + from app.config import settings + url = settings.DATABASE_URL + except Exception: + pass + + if not url: + raise RuntimeError( + "Set ALEMBIC_DATABASE_URL or DATABASE_URL for Alembic migrations. " + "Neither environment variable nor app.config.settings.DATABASE_URL is set." + ) + + # Strip psql wrapper if present (e.g., "psql 'postgresql://...'") + if url.startswith("psql '") and url.endswith("'"): + url = url[6:-1] + # Replace postgresql:// with postgresql+psycopg:// for psycopg3 - if url.startswith("postgresql://"): + if url.startswith("postgresql://") and not url.startswith("postgresql+psycopg://"): url = url.replace("postgresql://", "postgresql+psycopg://", 1) + + # Add sslmode=require for non-localhost connections (production) + if "sslmode=" not in url and "localhost" not in url and "127.0.0.1" not in url: + url = f"{url}{'&' if '?' in url else '?'}sslmode=require" + return url def run_migrations_offline() -> None: diff --git a/py_backend/app/crud.py b/py_backend/app/crud.py index 79a7d83a..e8f783d8 100644 --- a/py_backend/app/crud.py +++ b/py_backend/app/crud.py @@ -364,10 +364,19 @@ def create_caption(db: Session, image_id, title, prompt, model_code, raw_json, t if img.image_type == "drone_image": schema_id = "drone_caption@1.0.0" + # Handle "manual" model: if it doesn't exist in the database, set model to NULL + # This can happen if migrations didn't run (e.g., in production with fallback table creation) + model_value = model_code + if model_code == "manual": + manual_model = db.query(models.Models).filter(models.Models.m_code == 'manual').first() + if not manual_model: + logger.warning("'manual' model not found in database, setting caption.model to NULL") + model_value = None + caption = models.Captions( title=title, prompt=prompt, - model=model_code, + model=model_value, schema_id=schema_id, raw_json=raw_json, generated=text,