pybackend / routers /projects.py
vish85521's picture
Upload 17 files
dffa8c2 verified
Raw
History Blame Contribute Delete
4.95 kB
"""
Project management routes - create, list, and get projects
"""
import os
import uuid
import aiofiles
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, status
from sqlalchemy.orm import Session
from typing import List, Optional
from app.database import get_db
from app.models import User, Project
from app.schemas import ProjectCreate, ProjectResponse, ProjectListResponse
from app.dependencies import get_current_user
from app.config import get_settings
settings = get_settings()
router = APIRouter(prefix="/projects", tags=["Projects"])
# Allowed video extensions
ALLOWED_EXTENSIONS = {".mp4", ".mov", ".avi", ".webm", ".mkv"}
MAX_FILE_SIZE = 500 * 1024 * 1024 # 500MB
@router.post("", response_model=ProjectResponse, status_code=status.HTTP_201_CREATED)
async def create_project(
title: str = Form(...),
demographic_filter: Optional[str] = Form(None),
video: UploadFile = File(...),
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""
Create a new project with video upload
"""
# Validate file extension
file_ext = os.path.splitext(video.filename)[1].lower()
if file_ext not in ALLOWED_EXTENSIONS:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invalid file type. Allowed types: {', '.join(ALLOWED_EXTENSIONS)}"
)
# Create upload directory if it doesn't exist
upload_dir = os.path.join(settings.upload_dir, str(current_user.id))
os.makedirs(upload_dir, exist_ok=True)
# Generate unique filename
file_id = str(uuid.uuid4())
filename = f"{file_id}{file_ext}"
file_path = os.path.join(upload_dir, filename)
# Save file
try:
async with aiofiles.open(file_path, 'wb') as f:
# Read in chunks to handle large files
total_size = 0
while chunk := await video.read(1024 * 1024): # 1MB chunks
total_size += len(chunk)
if total_size > MAX_FILE_SIZE:
os.remove(file_path)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"File too large. Maximum size: {MAX_FILE_SIZE // (1024*1024)}MB"
)
await f.write(chunk)
except Exception as e:
if os.path.exists(file_path):
os.remove(file_path)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to save file: {str(e)}"
)
# Parse demographic filter
demo_filter = None
if demographic_filter:
import json
try:
demo_filter = json.loads(demographic_filter)
except json.JSONDecodeError:
pass
# Create project record
project = Project(
user_id=current_user.id,
title=title,
video_path=file_path,
demographic_filter=demo_filter,
status="PENDING"
)
db.add(project)
db.commit()
db.refresh(project)
# Queue VLM processing task (async)
from app.tasks import process_video_task
process_video_task.delay(str(project.id))
return project
@router.get("", response_model=List[ProjectListResponse])
async def list_projects(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""
List all projects for the current user
"""
projects = db.query(Project).filter(
Project.user_id == current_user.id
).order_by(Project.created_at.desc()).all()
return projects
@router.get("/{project_id}", response_model=ProjectResponse)
async def get_project(
project_id: str,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""
Get a specific project by ID
"""
project = db.query(Project).filter(
Project.id == project_id,
Project.user_id == current_user.id
).first()
if not project:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Project not found"
)
return project
@router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_project(
project_id: str,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""
Delete a project and its video file
"""
project = db.query(Project).filter(
Project.id == project_id,
Project.user_id == current_user.id
).first()
if not project:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Project not found"
)
# Delete video file
if os.path.exists(project.video_path):
os.remove(project.video_path)
# Delete project record
db.delete(project)
db.commit()