diff --git a/backend/src/routes/tags.py b/backend/src/routes/tags.py index c785590..d91ed7f 100644 --- a/backend/src/routes/tags.py +++ b/backend/src/routes/tags.py @@ -1,54 +1,93 @@ import logging from datetime import datetime, timedelta -from fastapi import APIRouter, status, Path -from src.models.tag import TagRead, TagCreate +import sqlalchemy.exc +from fastapi import APIRouter, status, Path, Depends, HTTPException +from sqlmodel import Session, select + +from src import database +from src.models.tag import TagRead, TagCreate, Tag router = APIRouter(prefix="/tags", tags=["Tags"]) @router.get("/", response_model=list[TagRead], summary="Get a list of all tags") -async def all_tags() -> list[TagRead]: +async def all_tags( + *, + session: Session = Depends(database.get_session) +) -> list[Tag]: """Returns a list of all tags.""" - return [ - TagRead( - name="Listening Lectures", - duration=timedelta(days=3, hours=5, minutes=47), - ), - TagRead( - name="Doing homework", - duration=timedelta(hours=14, minutes=10), - ) - ] + tags = session.exec(select(Tag)).all() + return tags @router.post("/", status_code=status.HTTP_201_CREATED, summary="Add a tag") -async def add_tag(tag: TagCreate): +async def add_tag( + *, + tag: TagCreate, + session: Session = Depends(database.get_session) +): """Add a tag.""" - print('adding tag', tag) + db_tag = Tag.from_orm(tag) + session.add(db_tag) + session.commit() + session.refresh(db_tag) + return db_tag @router.get("/{name}", response_model=TagRead, summary="Get a project by name") -async def get_tag(name: str = Path(..., title="Name of the tag")) -> TagRead: +async def get_tag( + *, + name: str = Path(..., title="Name of the tag"), + session: Session = Depends(database.get_session) +) -> Tag: """Fetch a project by name.""" - return TagRead( - name=name, - duration=timedelta(hours=3, minutes=2), - ) + try: + tag = session.exec(select(Tag).where(Tag.name == name)).one() + return tag + except sqlalchemy.exc.NoResultFound: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) @router.delete("/{name}", status_code=status.HTTP_204_NO_CONTENT, summary="Delete a tag by name") -async def delete_tag(name: str = Path(..., title="Name of the tag")): +async def delete_tag( + *, + name: str = Path(..., title="Name of the tag"), + session: Session = Depends(database.get_session) +): """Delete a tag specified by name.""" - logging.debug(f"Deleting tag {name}") + tag = session.exec(select(Tag).where(Tag.name == name)).one() + session.delete(tag) + session.commit() + # TODO: This method implicitly returns None, which will be converted to null by FastAPI, which triggers a + # warning, because the method returns with header HTTP_204_NO_CONTENT, but has content @router.patch("/{name}", summary="Apply partial updates to a tag by name") -async def patch_tag(tag: TagCreate, name: str = Path(..., title="Name of the tag")): +async def patch_tag( + *, + tag: TagCreate, + name: str = Path(..., title="Name of the tag"), + session: Session = Depends(database.get_session) +): """Apply partial updates to a tag.""" - logging.debug(f"Patching tag {name} with {tag}") + # Search for tag with name in database + try: + db_tag = session.exec(select(Tag).where(Tag.name == name)).one() + except sqlalchemy.exc.NoResultFound: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) + + # Set all provided arguments in the database project + for key, value in tag.dict(exclude_unset=True).items(): + setattr(db_tag, key, value) + + # Write modified tag to database + session.add(db_tag) + session.commit() + session.refresh(db_tag) + return db_tag