From ed5839e222ad54a60c0f5eed7ac359f259e4d466 Mon Sep 17 00:00:00 2001 From: sstent Date: Thu, 2 Oct 2025 04:58:42 -0700 Subject: [PATCH] fixing db tables and onplace upgrde --- ...data_migration_to_convert_serving_size_.py | 76 +++++++++++++++++++ ...0b0_ensure_serving_size_column_is_float.py | 38 ++++++++++ app/api/routes/meals.py | 22 ++---- main.py | 7 +- 4 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 alembic/versions/13939361fc35_data_migration_to_convert_serving_size_.py create mode 100644 alembic/versions/d0c142fbf0b0_ensure_serving_size_column_is_float.py diff --git a/alembic/versions/13939361fc35_data_migration_to_convert_serving_size_.py b/alembic/versions/13939361fc35_data_migration_to_convert_serving_size_.py new file mode 100644 index 0000000..0e7971b --- /dev/null +++ b/alembic/versions/13939361fc35_data_migration_to_convert_serving_size_.py @@ -0,0 +1,76 @@ +"""Data migration to convert serving_size to float + +Revision ID: 13939361fc35 +Revises: a11a3921f528 +Create Date: 2025-10-01 23:44:34.144506 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '13939361fc35' +down_revision: Union[str, None] = 'a11a3921f528' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """ + Data migration to convert existing string-based 'serving_size' values to floats. + This version uses a session to iterate through the data, providing more robust error handling. + """ + bind = op.get_bind() + from sqlalchemy.orm import sessionmaker + Session = sessionmaker(bind=bind) + session = Session() + + # Define a simple table structure for our purpose + food_table = sa.Table('foods', sa.MetaData(), + sa.Column('id', sa.Integer, primary_key=True), + sa.Column('name', sa.String), + sa.Column('serving_size', sa.String) # Treat it as String to be safe + ) + + try: + foods_to_update = session.query(food_table).all() + updated_count = 0 + + for food in foods_to_update: + # Check if serving_size is a string and needs conversion + if isinstance(food.serving_size, str): + try: + new_size = float(food.serving_size) + # Use session.execute for the update + session.execute( + food_table.update(). + where(food_table.c.id == food.id). + values(serving_size=new_size) + ) + updated_count += 1 + except (ValueError, TypeError): + print(f"Could not convert serving_size for Food ID {food.id} (Name: {food.name}). Value: '{food.serving_size}'") + + if updated_count > 0: + session.commit() + print(f"Successfully converted {updated_count} food items.") + else: + print("No food items required an update.") + + except Exception as e: + print(f"An error occurred during the data migration: {e}") + session.rollback() + finally: + session.close() + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + # A downgrade for this data migration is not practical as it would require + # converting floats back to strings, which could lead to loss of precision. + # It is better to back up the database before upgrading. + pass + # ### end Alembic commands ### diff --git a/alembic/versions/d0c142fbf0b0_ensure_serving_size_column_is_float.py b/alembic/versions/d0c142fbf0b0_ensure_serving_size_column_is_float.py new file mode 100644 index 0000000..da0bfd7 --- /dev/null +++ b/alembic/versions/d0c142fbf0b0_ensure_serving_size_column_is_float.py @@ -0,0 +1,38 @@ +"""Ensure serving_size column is Float + +Revision ID: d0c142fbf0b0 +Revises: 13939361fc35 +Create Date: 2025-10-02 00:27:05.400224 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'd0c142fbf0b0' +down_revision: Union[str, None] = '13939361fc35' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('foods', schema=None) as batch_op: + batch_op.alter_column('serving_size', + existing_type=sa.VARCHAR(), + type_=sa.Float(), + existing_nullable=True) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('foods', schema=None) as batch_op: + batch_op.alter_column('serving_size', + existing_type=sa.Float(), + type_=sa.VARCHAR(), + existing_nullable=True) + # ### end Alembic commands ### diff --git a/app/api/routes/meals.py b/app/api/routes/meals.py index 1c27f89..c113947 100644 --- a/app/api/routes/meals.py +++ b/app/api/routes/meals.py @@ -14,23 +14,11 @@ router = APIRouter() # Meals tab @router.get("/meals", response_class=HTMLResponse) async def meals_page(request: Request, db: Session = Depends(get_db)): - try: - from sqlalchemy.orm import joinedload - logging.info("DEBUG: Starting meals query with eager loading") - meals = db.query(Meal).options(joinedload(Meal.meal_foods).joinedload(MealFood.food)).all() - logging.info(f"DEBUG: Retrieved {len(meals)} meals") - foods = db.query(Food).all() - logging.info(f"DEBUG: Retrieved {len(foods)} foods") - - # Test template rendering with a simple test - logging.info("DEBUG: Testing template rendering...") - test_data = {"request": request, "meals": meals, "foods": foods} - return templates.TemplateResponse("meals.html", test_data) - - except Exception as e: - logging.error(f"DEBUG: Error in meals_page: {str(e)}", exc_info=True) - # Return a simple error response for debugging - return HTMLResponse(f"

Error in meals page

{str(e)}
{type(e).__name__}
") + from sqlalchemy.orm import joinedload + meals = db.query(Meal).options(joinedload(Meal.meal_foods).joinedload(MealFood.food)).all() + foods = db.query(Food).all() + return templates.TemplateResponse("meals.html", + {"request": request, "meals": meals, "foods": foods}) @router.post("/meals/upload") async def bulk_upload_meals(file: UploadFile = File(...), db: Session = Depends(get_db)): diff --git a/main.py b/main.py index 58d9b3c..8cb4463 100644 --- a/main.py +++ b/main.py @@ -253,12 +253,11 @@ def run_migrations(): if has_foods and (not has_alembic_version or not alembic_version_has_content): logging.info("DEBUG: Existing database detected. Stamping with initial migration.") - command.stamp(alembic_cfg, "head") + # Stamp with the specific initial migration that creates all tables + command.stamp(alembic_cfg, "cf94fca21104") logging.info("DEBUG: Database stamped successfully.") - else: - logging.info("DEBUG: No stamping needed or fresh database.") - # Now, run upgrades + # Now, run upgrades to bring the database to the latest version logging.info("DEBUG: Running alembic upgrade...") command.upgrade(alembic_cfg, "head") logging.info("DEBUG: Database migrations run successfully.")