Exception handling in the crud
module
#242
Replies: 2 comments 8 replies
-
That’s not exactly my point though. I think that in general, setting custom exceptions if you’re not creating a reusable module is not recommended as there is rapidly a lot of cases to cover and can easily get out of hand. I think that we need to rely as most as possible on already existing errors provided by the functions we use. For example: def create_book(title: string, genre_id: int, db: Session) -> Book:
genre = db.exec(select(Genre).where(Genre.id == genre_id).one() #raises GenreError with details if None
book = Book(title=title, genre=genre)
db.add(book) #raises BookError with details if title is already used
db.refresh(book)
return book This is how it should work for me. No custom errors, and in the same time, meaningful errors. If this kind of errors is not available, then we should split the crud functions so they raise no more than one error per function, meaning that we require valid arguments: # in crud
def get_genre_by_id(genre_id: int, db: Session) -> Genre | None:
genre = db.exec(select(Genre).where(Genre.id == genre_id).first() #no error raised
def create_book(title: str, genre: Genre, db: Session) -> Book: #genre must not be none bc type annotation
assert genre is not None # type annotation does not raise error, so we add this assertion to raise error
book = Book(title=title, genre=genre)
db.add(book) #raises DatabaseError with details if title is already used
db.refresh(book)
return book
# in route
@route.post()
def create_book(title: str, genre_id, db: Session = Depends()) -> Book:
genre = crud.get_genre_by_id(genre_id, db)
if genre is None:
raise HTTPException(404) from None
try:
return crud.create_book(title, genre, db)
except DatabaseError as e:
raise HTTPException(409) from e |
Beta Was this translation helpful? Give feedback.
-
What I miss in the conversation so far is the user-facing behavior. What should the user see? If it all boils down to a "Something went wrong" message on the frontend it does not really matter if you define different error classes. But maybe we want to return different response codes from the API in different circumstances. So, what's the behavior you're after? |
Beta Was this translation helpful? Give feedback.
-
@TimoBbz and I had a dicussion about the general exception handling in the backend.
I will briefly describe the situation:
To create new models, we have a
crud
module that handles the database connection. Thecrud
module has a functioncreate_model
. When calling the function, you have to pass the model information (including a tool variable) and the model gets created in the database. All possible tools are defined in a separate database table.Therefore, it can happen that the referenced tool doesn't exist during model creation. In this case, SQLAlchemy throws a
DatabaseError
(which is a general error and can occur in many cases). In my opinion, we should catch this possible error in the function itself and throw a custom defined exception, e.g.ToolNotFoundError
, which can be handled by the calling function.However, @TimoBbz argues that a developer should always pass valid values to the function and handle potential errors before.
I'd like to hear some general opinions and feedback about the way of handling exceptions.
Beta Was this translation helpful? Give feedback.
All reactions