-
Notifications
You must be signed in to change notification settings - Fork 58
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
"Solution" #33
base: main
Are you sure you want to change the base?
"Solution" #33
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,228 @@ | ||
from fastapi import APIRouter, Depends, HTTPException, Query | ||
from math import ceil | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The import statement is incorrect. It should be |
||
from fastapi import APIRouter, Depends, HTTPException, Query, Response | ||
from sqlalchemy.exc import IntegrityError | ||
from sqlalchemy.orm import Session, joinedload | ||
|
||
from database import get_db | ||
from database.models import MovieModel, CountryModel, GenreModel, ActorModel, LanguageModel | ||
|
||
from schemas.movies import ( | ||
PaginationPages, | ||
MovieRead, | ||
MovieCreate, | ||
MovieUpdate, | ||
) | ||
|
||
router = APIRouter() | ||
|
||
|
||
# Write your code here | ||
@router.get("/movies/", response_model=PaginationPages) | ||
def get_movies( | ||
page: int = Query(1, ge=1), | ||
per_page: int = Query(10, ge=1, le=20), | ||
db: Session = Depends(get_db) | ||
): | ||
skip = (page - 1) * per_page | ||
limit = per_page | ||
|
||
movie_query = db.query(MovieModel).order_by(MovieModel.id.desc()) | ||
total_items = movie_query.count() | ||
db_movies = movie_query.offset(skip).limit(limit).all() | ||
if not db_movies: | ||
raise HTTPException(status_code=404, detail="No movies found.") | ||
total_pages = ceil(total_items / per_page) | ||
|
||
prev_page = f"/theater/movies/?page={page - 1}&per_page={per_page}" if page > 1 else None | ||
next_page = f"/theater/movies/?page={page + 1}&per_page={per_page}" if page < total_pages else None | ||
|
||
return PaginationPages( | ||
movies=db_movies, | ||
prev_page=prev_page, | ||
next_page=next_page, | ||
total_pages=total_pages, | ||
total_items=total_items | ||
) | ||
|
||
|
||
def get_or_create_genre(genre: str, db: Session = Depends(get_db)): | ||
db_genre = db.query(GenreModel).filter(GenreModel.name == genre).first() | ||
if not db_genre: | ||
db_genre = GenreModel(name=genre) | ||
db.add(db_genre) | ||
db.commit() | ||
db.refresh(db_genre) | ||
|
||
return db_genre | ||
|
||
|
||
def get_or_create_actor(actor: str, db: Session = Depends(get_db)): | ||
db_actor = db.query(ActorModel).filter(ActorModel.name == actor).first() | ||
if not db_actor: | ||
db_actor = ActorModel(name=actor) | ||
db.add(db_actor) | ||
db.commit() | ||
db.refresh(db_actor) | ||
|
||
return db_actor | ||
|
||
|
||
def get_or_create_country(country: str, db: Session = Depends(get_db)): | ||
db_country = db.query(CountryModel).filter(CountryModel.code == country).first() | ||
if not db_country: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Comment on lines
+70
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
db_country = CountryModel(code=country) | ||
db.add(db_country) | ||
db.commit() | ||
db.refresh(db_country) | ||
|
||
return db_country | ||
|
||
|
||
def get_or_create_language(language: str, db: Session = Depends(get_db)): | ||
db_language = db.query(LanguageModel).filter(LanguageModel.name == language).first() | ||
if not db_language: | ||
db_language = LanguageModel(name=language) | ||
db.add(db_language) | ||
db.commit() | ||
db.refresh(db_language) | ||
|
||
return db_language | ||
|
||
|
||
@router.post("/movies/", response_model=MovieRead, status_code=201) | ||
def create_movie(movie: MovieCreate, db: Session = Depends(get_db)): | ||
existing_movie = db.query(MovieModel).filter( | ||
MovieModel.name == movie.name, | ||
MovieModel.date == movie.date | ||
).first() | ||
|
||
if existing_movie: | ||
raise HTTPException( | ||
status_code=409, | ||
detail=f"A movie with the name '{movie.name}' and release date '{movie.date}' already exists." | ||
) | ||
|
||
country = get_or_create_country(movie.country, db) | ||
|
||
genres = [] | ||
for genre_name in movie.genres: | ||
genre = get_or_create_genre(genre_name, db) | ||
genres.append(genre) | ||
|
||
actors = [] | ||
for actor_name in movie.actors: | ||
actor = get_or_create_actor(actor_name, db) | ||
actors.append(actor) | ||
|
||
languages = [] | ||
for language_name in movie.languages: | ||
language = get_or_create_language(language_name, db) | ||
languages.append(language) | ||
|
||
db_movie = MovieModel( | ||
name=movie.name, | ||
date=movie.date, | ||
score=movie.score, | ||
overview=movie.overview, | ||
status=movie.status, | ||
budget=movie.budget, | ||
revenue=movie.revenue, | ||
country_id=country.id, | ||
) | ||
|
||
db_movie.genres = genres | ||
db_movie.actors = actors | ||
db_movie.languages = languages | ||
db.add(db_movie) | ||
Comment on lines
+133
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After creating the movie, you should add the genres, actors, and languages to the
Comment on lines
+133
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure that genres, actors, and languages are added to the |
||
db.commit() | ||
db.refresh(db_movie) | ||
|
||
return db_movie | ||
|
||
|
||
@router.get("/movies/{movie_id}/", response_model=MovieRead) | ||
def get_movie_details(movie_id: int, db: Session = Depends(get_db)): | ||
db_movie = db.query(MovieModel).options( | ||
joinedload(MovieModel.country), | ||
joinedload(MovieModel.genres), | ||
joinedload(MovieModel.actors), | ||
joinedload(MovieModel.languages) | ||
).filter(MovieModel.id == movie_id).first() | ||
|
||
if db_movie is None: | ||
raise HTTPException(status_code=404, detail="Movie with the given ID was not found.") | ||
|
||
return MovieRead( | ||
id=db_movie.id, | ||
name=db_movie.name, | ||
date=db_movie.date, | ||
score=db_movie.score, | ||
overview=db_movie.overview, | ||
status=db_movie.status, | ||
budget=db_movie.budget, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
revenue=db_movie.revenue, | ||
country={ | ||
"id": db_movie.country.id, | ||
"code": db_movie.country.code, | ||
"name": db_movie.country.name if db_movie.country.name else None | ||
}, | ||
genres=[{"id": genre.id, "name": genre.name} for genre in db_movie.genres], | ||
actors=[{"id": actor.id, "name": actor.name} for actor in db_movie.actors], | ||
languages=[{"id": language.id, "name": language.name} for language in db_movie.languages] | ||
) | ||
|
||
|
||
@router.delete("/movies/{movie_id}/") | ||
def delete_movie(movie_id: int, db: Session = Depends(get_db)): | ||
db_movie = db.query(MovieModel).filter(MovieModel.id == movie_id).first() | ||
|
||
if db_movie is None: | ||
raise HTTPException(status_code=404, detail="Movie with the given ID was not found.") | ||
|
||
db.delete(db_movie) | ||
db.commit() | ||
|
||
return Response(status_code=204) | ||
|
||
|
||
@router.patch("/movies/{movie_id}/", status_code=200) | ||
def update_movie(movie_id, movie: MovieUpdate, db: Session = Depends(get_db)): | ||
db_movie = db.query(MovieModel).filter(MovieModel.id == movie_id).first() | ||
|
||
if not db_movie: | ||
raise HTTPException( | ||
status_code=404, | ||
detail="Movie with the given ID was not found." | ||
) | ||
|
||
if movie.name: | ||
db_movie.name = movie.name | ||
|
||
if movie.date: | ||
db_movie.date = movie.date | ||
|
||
if movie.score is not None: | ||
if not (0 <= movie.score <= 100): | ||
raise HTTPException(status_code=400, detail="Invalid input data.") | ||
db_movie.score = movie.score | ||
|
||
if movie.overview: | ||
db_movie.overview = movie.overview | ||
|
||
if movie.status: | ||
db_movie.status = movie.status | ||
|
||
if movie.budget is not None: | ||
if movie.budget < 0: | ||
raise HTTPException(status_code=400, detail="Invalid input data.") | ||
db_movie.budget = movie.budget | ||
|
||
if movie.revenue is not None: | ||
if movie.revenue < 0: | ||
raise HTTPException(status_code=400, detail="Invalid input data.") | ||
db_movie.revenue = movie.revenue | ||
|
||
db.commit() | ||
db.refresh(db_movie) | ||
|
||
return {"detail": "Movie updated successfully."} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,87 @@ | ||
# Write your code here | ||
import datetime | ||
from pydantic import BaseModel | ||
from typing import List, Optional | ||
|
||
from database.models import MovieStatusEnum | ||
|
||
|
||
class GenreRead(BaseModel): | ||
id: int | ||
name: str | ||
|
||
|
||
class ActorRead(BaseModel): | ||
id: int | ||
name: str | ||
|
||
|
||
class CountryRead(BaseModel): | ||
id: int | ||
code: str | ||
name: Optional[str] | ||
|
||
|
||
class LanguageRead(BaseModel): | ||
id: int | ||
name: str | ||
|
||
|
||
class Movies(BaseModel): | ||
id: int | ||
name: str | ||
date: datetime.date | ||
score: float | ||
overview: str | ||
|
||
class Config: | ||
from_attributes = True | ||
|
||
|
||
class MovieUpdate(BaseModel): | ||
name: Optional[str] = None | ||
date: Optional[datetime.date] = None | ||
score: Optional[float] = None | ||
overview: Optional[str] = None | ||
status: Optional[str] = None | ||
budget: Optional[float] = None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
revenue: Optional[float] = None | ||
|
||
|
||
class MovieCreate(BaseModel): | ||
name: str | ||
date: datetime.date | ||
score: float | ||
overview: str | ||
status: MovieStatusEnum | ||
budget: float | ||
revenue: float | ||
country: str | ||
genres: List[str] | ||
actors: List[str] | ||
languages: List[str] | ||
|
||
|
||
class MovieRead(BaseModel): | ||
id: int | ||
name: str | ||
date: datetime.date | ||
score: float | ||
overview: str | ||
status: MovieStatusEnum | ||
budget: float | ||
revenue: float | ||
country: CountryRead | ||
genres: List[GenreRead] | ||
actors: List[ActorRead] | ||
languages: List[LanguageRead] | ||
|
||
class Config: | ||
orm_mode = True | ||
|
||
|
||
class PaginationPages(BaseModel): | ||
movies: List[Movies] | ||
prev_page: Optional[str] | ||
next_page: Optional[str] | ||
total_pages: int | ||
total_items: int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement
from math import ceil
is incorrect. It should befrom math import ceil
instead offrom math import ceil /
.