Fix internal server error when creating tasks and other endpoints

This commit is contained in:
Automated Action 2025-05-16 06:03:23 +00:00
parent 73d7a71140
commit d48cd52fb7
6 changed files with 114 additions and 13 deletions

View File

@ -22,8 +22,8 @@ def upgrade():
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), nullable=False),
sa.Column('title', sa.String(length=100), nullable=False), sa.Column('title', sa.String(length=100), nullable=False),
sa.Column('description', sa.Text(), nullable=True), sa.Column('description', sa.Text(), nullable=True),
sa.Column('priority', sa.Enum('LOW', 'MEDIUM', 'HIGH', name='taskpriority'), default='MEDIUM'), sa.Column('priority', sa.Enum('low', 'medium', 'high', name='taskpriority'), default='medium'),
sa.Column('status', sa.Enum('TODO', 'IN_PROGRESS', 'DONE', name='taskstatus'), default='TODO'), sa.Column('status', sa.Enum('todo', 'in_progress', 'done', name='taskstatus'), default='todo'),
sa.Column('due_date', sa.DateTime(), nullable=True), sa.Column('due_date', sa.DateTime(), nullable=True),
sa.Column('completed', sa.Boolean(), default=False), sa.Column('completed', sa.Boolean(), default=False),
sa.Column('created_at', sa.DateTime(), default=sa.func.now()), sa.Column('created_at', sa.DateTime(), default=sa.func.now()),

View File

@ -5,7 +5,7 @@ from typing import Any, Dict, List, Optional, Union
from pydantic import AnyHttpUrl, field_validator from pydantic import AnyHttpUrl, field_validator
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings
DB_DIR = Path("/app") / "storage" / "db" DB_DIR = Path("/app/storage/db")
DB_DIR.mkdir(parents=True, exist_ok=True) DB_DIR.mkdir(parents=True, exist_ok=True)
class Settings(BaseSettings): class Settings(BaseSettings):
@ -29,8 +29,9 @@ class Settings(BaseSettings):
# Database configuration # Database configuration
SQLALCHEMY_DATABASE_URL: str = f"sqlite:///{DB_DIR}/db.sqlite" SQLALCHEMY_DATABASE_URL: str = f"sqlite:///{DB_DIR}/db.sqlite"
class Config: model_config = {
case_sensitive = True "case_sensitive": True
}
settings = Settings() settings = Settings()

View File

@ -45,7 +45,11 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
if isinstance(obj_in, dict): if isinstance(obj_in, dict):
update_data = obj_in update_data = obj_in
else: else:
update_data = obj_in.model_dump(exclude_unset=True) # Handle both Pydantic v1 and v2
if hasattr(obj_in, "model_dump"):
update_data = obj_in.model_dump(exclude_unset=True)
else:
update_data = obj_in.dict(exclude_unset=True)
for field in obj_data: for field in obj_data:
if field in update_data: if field in update_data:
setattr(db_obj, field, update_data[field]) setattr(db_obj, field, update_data[field])
@ -55,7 +59,8 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
return db_obj return db_obj
def remove(self, db: Session, *, id: int) -> ModelType: def remove(self, db: Session, *, id: int) -> ModelType:
obj = db.query(self.model).get(id) obj = db.query(self.model).filter(self.model.id == id).first()
db.delete(obj) if obj:
db.commit() db.delete(obj)
db.commit()
return obj return obj

44
app/db/init_db.py Normal file
View File

@ -0,0 +1,44 @@
import os
import subprocess
from pathlib import Path
from sqlalchemy import text
from sqlalchemy.orm import Session
from app.db.session import engine
from app.core.config import settings
def init_db() -> None:
"""Initialize database with required tables and data."""
# Ensure database directory exists
Path(settings.DB_DIR).mkdir(parents=True, exist_ok=True)
# Try to connect to check if the database is accessible
with engine.connect() as conn:
try:
conn.execute(text("SELECT 1"))
print("Database connection successful")
except Exception as e:
print(f"Database connection error: {e}")
raise
# Run alembic upgrade to create tables
try:
# Get the project root directory (where alembic.ini is located)
project_root = Path(__file__).parent.parent.parent.absolute()
# Change to project root directory and run alembic
os.chdir(project_root)
subprocess.run(["alembic", "upgrade", "head"], check=True)
print("Database migration successful")
except subprocess.CalledProcessError as e:
print(f"Database migration error: {e}")
raise
print("Database initialized successfully")
if __name__ == "__main__":
init_db()

View File

@ -33,8 +33,9 @@ class TaskInDBBase(TaskBase):
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
class Config: model_config = {
from_attributes = True "from_attributes": True
}
class Task(TaskInDBBase): class Task(TaskInDBBase):

52
main.py
View File

@ -1,8 +1,25 @@
from fastapi import FastAPI import sys
import os
from pathlib import Path
# Add project root to Python path for imports in alembic migrations
project_root = Path(__file__).parent.absolute()
sys.path.insert(0, str(project_root))
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from app.api.routers import api_router from app.api.routers import api_router
from app.core.config import settings from app.core.config import settings
from app.db import init_db
# Initialize the database on startup
try:
init_db.init_db()
except Exception as e:
print(f"Error initializing database: {e}")
# Continue with app startup even if DB init fails, to allow debugging
app = FastAPI(title=settings.PROJECT_NAME) app = FastAPI(title=settings.PROJECT_NAME)
@ -15,6 +32,14 @@ app.add_middleware(
allow_headers=["*"], allow_headers=["*"],
) )
# Add exception handlers for better error reporting
@app.exception_handler(Exception)
async def validation_exception_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=500,
content={"detail": f"Internal Server Error: {str(exc)}"},
)
app.include_router(api_router) app.include_router(api_router)
@ -24,3 +49,28 @@ def health_check():
Health check endpoint to verify the application is running correctly Health check endpoint to verify the application is running correctly
""" """
return {"status": "ok"} return {"status": "ok"}
@app.get("/db-test", tags=["health"])
def test_db_connection():
"""
Test database connection and table creation
"""
from sqlalchemy import text
from app.db.session import engine
try:
with engine.connect() as conn:
# Try to select from the task table to verify it exists
result = conn.execute(text("SELECT COUNT(*) FROM task")).scalar()
return {
"status": "ok",
"connection": "successful",
"task_count": result
}
except Exception as e:
return {
"status": "error",
"connection": "failed",
"error": str(e)
}