-
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
develop #27
base: main
Are you sure you want to change the base?
develop #27
Changes from all 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 |
---|---|---|
@@ -0,0 +1,81 @@ | ||
from datetime import datetime | ||
|
||
from sqlalchemy.orm import Session | ||
|
||
from database.models import (ActorModel, CountryModel, GenreModel, | ||
LanguageModel, MovieModel) | ||
from schemas.movies import MovieCreateRequest | ||
|
||
|
||
def get_movies_pagination(offset: int, per_page: int, db: Session) -> tuple[list[type[MovieModel]], int]: | ||
movies = db.query(MovieModel).order_by(MovieModel.id.desc()).offset(offset).limit(per_page).all() | ||
movies_count = db.query(MovieModel).count() | ||
return movies, movies_count | ||
|
||
|
||
def get_movie_by_id(db: Session, movie_id: int) -> MovieModel | None: | ||
return db.query(MovieModel).filter(MovieModel.id == movie_id).first() | ||
|
||
|
||
def get_create(name: str, date: datetime.date, db: Session) -> MovieModel | None: | ||
return db.query(MovieModel).filter(MovieModel.name == name, MovieModel.date == date).first() | ||
|
||
|
||
def crud_create_movie(movie: MovieCreateRequest, db: Session) -> MovieModel: | ||
country = db.query(CountryModel).filter(CountryModel.code == movie.country).first() | ||
if not country: | ||
country = CountryModel(code=movie.country) | ||
db.add(country) | ||
db.commit() | ||
db.refresh(country) | ||
|
||
genres = [] | ||
for genre_name in movie.genres: | ||
genre = db.query(GenreModel).filter(GenreModel.name == genre_name).first() | ||
if not genre: | ||
genre = GenreModel(name=genre_name) | ||
db.add(genre) | ||
db.commit() | ||
db.refresh(genre) | ||
Comment on lines
+38
to
+39
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. Committing within a loop can be inefficient. Consider batching these operations and committing once after the loop to reduce the number of database transactions. |
||
genres.append(genre) | ||
|
||
actors = [] | ||
for actor_name in movie.actors: | ||
actor = db.query(ActorModel).filter(ActorModel.name == actor_name).first() | ||
if not actor: | ||
actor = ActorModel(name=actor_name) | ||
db.add(actor) | ||
db.commit() | ||
db.refresh(actor) | ||
Comment on lines
+48
to
+49
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. Similar to the genres loop, committing within the actors loop can be optimized by batching the operations and committing once after the loop. |
||
actors.append(actor) | ||
|
||
languages = [] | ||
for language_name in movie.languages: | ||
language = db.query(LanguageModel).filter(LanguageModel.name == language_name).first() | ||
if not language: | ||
language = LanguageModel(name=language_name) | ||
db.add(language) | ||
db.commit() | ||
db.refresh(language) | ||
Comment on lines
+58
to
+59
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. As with the previous loops, consider batching the language operations and committing once after the loop to improve efficiency. |
||
languages.append(language) | ||
|
||
new_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.add(new_movie) | ||
db.commit() | ||
db.refresh(new_movie) | ||
|
||
new_movie.genres = genres | ||
new_movie.actors = actors | ||
new_movie.languages = languages | ||
db.commit() | ||
|
||
return new_movie |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,15 @@ | ||
import os | ||
|
||
from database.models import ( | ||
Base, | ||
MovieModel | ||
) | ||
from database.models import Base, MovieModel | ||
from database.session_sqlite import reset_sqlite_database as reset_database | ||
|
||
environment = os.getenv("ENVIRONMENT", "developing") | ||
|
||
if environment == "testing": | ||
from database.session_sqlite import ( | ||
get_sqlite_db_contextmanager as get_db_contextmanager, | ||
get_sqlite_db as get_db | ||
) | ||
from database.session_sqlite import get_sqlite_db as get_db | ||
from database.session_sqlite import \ | ||
get_sqlite_db_contextmanager as get_db_contextmanager | ||
else: | ||
from database.session_postgresql import ( | ||
get_postgresql_db_contextmanager as get_db_contextmanager, | ||
get_postgresql_db as get_db | ||
) | ||
from database.session_postgresql import get_postgresql_db as get_db | ||
from database.session_postgresql import \ | ||
get_postgresql_db_contextmanager as get_db_contextmanager |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,136 @@ | ||
from fastapi import APIRouter, Depends, HTTPException, Query | ||
from fastapi import APIRouter, Depends, HTTPException, Query, status | ||
from sqlalchemy import func | ||
from sqlalchemy.exc import IntegrityError | ||
from sqlalchemy.orm import Session, joinedload | ||
from starlette.requests import Request | ||
|
||
from crud.movies import (crud_create_movie, get_create, get_movie_by_id, | ||
get_movies_pagination) | ||
from database import get_db | ||
from database.models import MovieModel, CountryModel, GenreModel, ActorModel, LanguageModel | ||
|
||
from database.models import (ActorModel, CountryModel, GenreModel, | ||
LanguageModel, MovieModel) | ||
from schemas.movies import (ActorResponse, CountryResponse, GenreResponse, | ||
LanguageResponse, MovieCreateRequest, | ||
MovieCreateResponse, MovieDetailResponse, | ||
MovieListResponse, MovieSchema, MovieUpdateRequest) | ||
|
||
router = APIRouter() | ||
|
||
|
||
# Write your code here | ||
@router.get("/movies/", response_model=MovieListResponse) | ||
def get_movies( | ||
page: int = Query(1, ge=1, description="Page number"), | ||
per_page: int = Query(10, ge=1, le=20, description="Items per page"), | ||
db: Session = Depends(get_db), | ||
): | ||
total_items = db.query(MovieModel).count() | ||
|
||
if total_items == 0: | ||
raise HTTPException(status_code=404, detail="No movies found.") | ||
|
||
total_pages = (total_items + per_page - 1) // per_page | ||
|
||
if page > total_pages: | ||
raise HTTPException(status_code=404, detail="Page not found.") | ||
|
||
offset = (page - 1) * per_page | ||
movies, total_items = get_movies_pagination(offset, per_page, db) | ||
|
||
movies_list = [ | ||
MovieSchema( | ||
id=movie.id, | ||
name=movie.name, | ||
date=str(movie.date), | ||
score=movie.score, | ||
overview=movie.overview | ||
) | ||
for movie in movies | ||
] | ||
|
||
base_url = "/theater/movies/" | ||
prev_page = f"{base_url}?page={page - 1}&per_page={per_page}" if page > 1 else None | ||
next_page = f"{base_url}?page={page + 1}&per_page={per_page}" if page < total_pages else None | ||
|
||
return MovieListResponse( | ||
movies=movies_list, | ||
prev_page=prev_page, | ||
next_page=next_page, | ||
total_pages=total_pages, | ||
total_items=total_items | ||
) | ||
|
||
|
||
@router.post("/movies/", response_model=MovieCreateResponse, status_code=201) | ||
def create_movie(movie: MovieCreateRequest, db: Session = Depends(get_db)): | ||
existing_movie = get_create(movie.name, movie.date, db) | ||
|
||
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 function |
||
if existing_movie: | ||
raise HTTPException( | ||
status_code=409, | ||
detail=f"A movie with the name '{movie.name}' and release date '{movie.date}' already exists." | ||
) | ||
|
||
try: | ||
new_movie = crud_create_movie(movie, db) | ||
return MovieCreateResponse.model_validate(new_movie) | ||
except ValueError: | ||
raise HTTPException( | ||
status_code=status.HTTP_400_BAD_REQUEST, | ||
detail="Invalid input data." | ||
) | ||
|
||
|
||
@router.get("/movies/{movie_id}/", response_model=MovieDetailResponse) | ||
def get_movie_details(movie_id: int, db: Session = Depends(get_db)): | ||
movie_details = get_movie_by_id(db, movie_id) | ||
if not movie_details: | ||
raise HTTPException( | ||
status_code=status.HTTP_404_NOT_FOUND, | ||
detail="Movie with the given ID was not found." | ||
) | ||
return movie_details | ||
|
||
|
||
@router.delete("/movies/{movie_id}/", status_code=status.HTTP_204_NO_CONTENT) | ||
def delete_movie(movie_id: int, db: Session = Depends(get_db)): | ||
movie = db.query(MovieModel).filter(MovieModel.id == movie_id).first() | ||
|
||
if not movie: | ||
raise HTTPException( | ||
status_code=status.HTTP_404_NOT_FOUND, | ||
detail="Movie with the given ID was not found." | ||
) | ||
|
||
db.delete(movie) | ||
db.commit() | ||
return None | ||
|
||
|
||
@router.patch("/movies/{movie_id}/") | ||
def update_movie(movie_id: int, movie_data: MovieUpdateRequest, db: Session = Depends(get_db)): | ||
movie = db.query(MovieModel).filter(MovieModel.id == movie_id).first() | ||
|
||
if not movie: | ||
raise HTTPException( | ||
status_code=status.HTTP_404_NOT_FOUND, | ||
detail="Movie with the given ID was not found." | ||
) | ||
|
||
if movie_data.name: | ||
movie.name = movie_data.name | ||
if movie_data.date: | ||
movie.date = movie_data.date | ||
if movie_data.score is not None: | ||
movie.score = movie_data.score | ||
if movie_data.overview: | ||
movie.overview = movie_data.overview | ||
if movie_data.status: | ||
movie.status = movie_data.status | ||
if movie_data.budget is not None: | ||
movie.budget = movie_data.budget | ||
if movie_data.revenue is not None: | ||
movie.revenue = movie_data.revenue | ||
|
||
db.commit() | ||
|
||
return {"detail": "Movie updated successfully."} |
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 function name
get_create
is misleading. It suggests both retrieval and creation, but it only retrieves a movie. Consider renaming it to something likeget_movie_by_name_and_date
for clarity.