Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nick mack branch #4

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions api/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from fastapi import FastAPI, HTTPException, status
from schema.book import Book, BookCreate
from schema.review import Review, ReviewCreate

app = FastAPI()

Expand All @@ -12,6 +13,18 @@ def get_next_book_id() -> int:
book_id_counter += 1
return next_id

books.append(
Book(
id=get_next_book_id(),
title="Green Eggs and Ham",
author="Dr.Suess",
publication_year=1980,
genre="Self-help",
reviews=[Review(id=1,reviewer="LeBron James", review="Life changing. A true masterpiece.", rating=5),
Review(id=2,reviewer="LeBron James", review="Read it again. Mid.", rating=3)],
)
)

@app.get("/")
async def root():
return "The root endpoint of a service (/) is often used as a health check to determine whether the service is working or not."
Expand All @@ -24,7 +37,7 @@ async def get_books():
return books

@app.get(
"/books/{book_id}",
"/books/{book_id}",
)
async def get_book(book_id: int) -> Book:
ret = next((book for book in books if book.id == book_id), None)
Expand All @@ -40,6 +53,18 @@ async def get_book(book_id: int) -> Book:
# Will it/they return one or potentially several books?
# Can you safely handle the case where no books are returned? What HTTP status code would that be?

# @app.get("/books/bookreviews/{book_reviews}")
# async def get_book_reviews(book_reviws: str) -> list[Book]:
# return(book_review for book in books if )

@app.get("/books/author/{author_last_name}")
async def get_book_author(author_last_name: str) -> list[Book]:
return (book for book in books if author_last_name in book.author)

@app.get("/books/publication_year/{publication_year}")
async def get_book_publication_year(publication_year: int) -> list[Book]:
return (book for book in books if publication_year == book.publication_year)

@app.post(
"/books",
status_code=status.HTTP_201_CREATED,
Expand All @@ -49,16 +74,25 @@ async def create_book(book: BookCreate) -> Book:
books.append(new_book)
return new_book

# @app.put("/books/bookreview/{book_review}",)
# async def post_book_reviews(book_title:BookBase,_review: ReviewCreate) -> Review:
# book_to_update = next((book for book in books if book_title == book.title), None)
# if book_title in book.title:
# book.review.append(book_review)


@app.put(
"/books/{book_id}",
)
async def update_book(book: BookCreate, book_id: int) -> Book:
book_to_update = next((book for book in books if book.id == book_id), None)
if book_to_update:
book_to_update.title = book.title
book_to_update.genre = book.genre
book_to_update.author = book.author
book_to_update.publication_year = book.publication_year
book_to_update.rating = book.rating
book_to_update.rating = book.review.rating
book_to_update.reviews = book.reviews
else:
book_to_update = Book.from_base(book, book_id)
books.append(book_to_update)
Expand All @@ -79,3 +113,4 @@ async def brew():
status_code=status.HTTP_418_IM_A_TEAPOT,
detail="Cannot brew coffee with a teapot!"
)

22 changes: 17 additions & 5 deletions api/schema/book.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
from typing import Optional

from pydantic import BaseModel
from typing import Optional, List
from pydantic import BaseModel, computed_field
from .review import Review
import statistics

class BookBase(BaseModel):
title: str
author: str
genre: str
publication_year: Optional[int] = None
rating: Optional[int] = None
reviews: List[Review] = []

@computed_field
@property
def avg_rating(self) -> float:
ratings = [review.rating for review in self.reviews if review.rating is not None]
if not ratings:
return 0.0
else:
return statistics.mean(ratings)

# TODO
# Add a 'genre' field here. You'll need to add it in a few other places as well!
# Bonus: try implementing genre as an enum rather than a string
Expand All @@ -22,9 +33,10 @@ def from_base(base: BookBase, id: int):
return Book(
id = id,
title = base.title,
genre = base.genre,
author = base.author,
publication_year = base.publication_year,
rating = base.rating
reviews = base.reviews,
)


Expand Down
21 changes: 21 additions & 0 deletions api/schema/review.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from typing import Optional
from pydantic import BaseModel, conint

class ReviewBase(BaseModel):
reviewer: Optional[str] = None
review: Optional[str] = None
rating: Optional[conint(ge=0, le=5)] = None

class ReviewCreate(ReviewBase):
pass

class Review(ReviewBase):
id: int

def from_base(base: ReviewBase, id: int):
return Review(
id = id,
reviewer = base.reviewer,
rewview = base.review,
rating = base.rating
)