@leroysheep / MovieWebApp / commits / b1a1640b82

fixing crud and working on delete query

Lee Roy Stevenson committed May 19, 2025 at 17:07 UTC b1a1640b82ca10479e96b38429d67e69b227d900
4 files changed +98 -99
app.py
+14 -6
@@ -27,15 +27,23 @@ def user_movies(user_id):
27 user=chosen_user)
28 elif request.method == "POST":
29 chosen_user = data_manager.get_user(user_id)
30 - movie_title = request.form["movie_title"]
30 + movie_title = request.form["name"]
31 with data_manager.SessionFactory() as session:
32 movie = session.query(Movie).filter_by(name=movie_title).first()
33 + if movie is None:
34 + try:
35 + movie = data_manager.set_movie(movie_title)
36 + session.add(movie)
37 + data_manager.set_user_movies(user_id=user_id, movie_id=movie.id, rating=movie.rating)
38 + session.commit()
39 + user_movies_list = data_manager.get_user_movies(user_id)
40 + return render_template("user_movies.html", user_movies=user_movies_list,
41 + user=chosen_user, success=True)
42 + except Exception as e:
43 + session.rollback()
44 + return render_template("user_movies.html", user_movies=user_movies_list,
45 + user=chosen_user, success=False)
46
34 - data_manager.set_user_movies(user_id, movie.id, movie.rating, movie.user_rating)
35 - success = True
36 - user_movies_list = data_manager.get_user_movies(user_id)
37 - return render_template("user_movies.html", user_movies=user_movies_list,
38 - user=chosen_user, success=success)
47
48 @app.route('/users/new', methods=["GET", "POST"])
49 def new_user():
data_models.py
+10 -9
@@ -22,15 +22,13 @@ class UserMovie(Base):
22 id = Column(Integer, primary_key=True)
23 user_id = Column('user_id', Integer, ForeignKey('users.id'))
24 movie_id = Column('movie_id', Integer, ForeignKey('movies.id'))
25 - rating = Column(Float)
25 user_rating = Column('user_rating', Float, default=0.0 )# Add the rating column here
26 + users = relationship("User", back_populates="user_movies", overlaps="users,movies")
27 + movies = relationship("Movie", back_populates="user_movies", overlaps="users,movies")
28
29 def __repr__(self):
29 - result = ""
30 - for user in session.query(User).all():
31 - result += (f"<UserMovie(user_id={self.user_id}, movie_id={self.movie_id}, "
32 - f"rating={self.rating})>\n")
33 - return result
30 + return (f"<UserMovie(user_id={self.user_id}, movie_id={self.movie_id}, "
31 + f"user_rating={self.user_rating})>")
32
33 # Define the User model
34 class User(Base):
@@ -38,7 +36,8 @@ class User(Base):
36 id = Column(Integer, primary_key=True)
37 name = Column(String)
38 movies = relationship("Movie", secondary="user_movies",
41 - back_populates="users")
39 + back_populates="users", overlaps="user_movies,movies")
40 + user_movies = relationship("UserMovie", back_populates="users", overlaps="user_movies,movies")
41
42 def __repr__(self):
43 return f"<User(name='{self.name}', id={self.id if self.id else 'None'})>"
@@ -54,10 +53,12 @@ class Movie(Base):
53 poster = Column(String)
54 rating = Column(Float)
55 users = relationship("User", secondary="user_movies",
57 - back_populates="movies")
56 + back_populates="movies", overlaps="user_movies,users")
57 + user_movies = relationship("UserMovie", back_populates="movies",
58 + overlaps="user_movies,users")
59
60 def __repr__(self):
60 - return f"<Movie(name='{self.name}', id={self.id if self.id else 'None'})>"
61 + return f"<Movie(name={self.name}, id={self.id if self.id else 'None'})>"
62
63
64 if __name__ == "__main__":
datamanager/data_manager_interface.py
+1 -1
@@ -15,6 +15,6 @@ class DataManagerInterface(ABC):
15 pass
16
17 @abstractmethod
18 - def set_user_movies(self, user_id, movie):
18 + def set_user_movies(self, user_id, movie_id, user_rating):
19 pass
20
datamanager/sqlite_data_manager.py
+73 -83
@@ -2,7 +2,8 @@
2 from sqlalchemy import create_engine
3 from sqlalchemy.orm import sessionmaker, joinedload, Session
4 from contextlib import contextmanager
5 -from typing import List, Dict, Any
5 +from typing import List, Dict, Any, Type
6 +
7 from data_models import Base, User, Movie, UserMovie
8 from movie_api import OMDBClient
9 from datamanager.data_manager_interface import DataManagerInterface
@@ -34,12 +35,12 @@ class SQliteDataManager(DataManagerInterface):
35 session.commit()
36 except Exception:
37 session.rollback()
37 - raise
38 + raise ConnectionError("Database connection error!")
39 finally:
40 session.close()
41
42 @property
42 - def users(self) -> List[User]:
43 + def users(self) -> list[Type[User]]:
44 """
45 Getter for users.
46 Returns: a list of User objects.
@@ -49,7 +50,7 @@ class SQliteDataManager(DataManagerInterface):
50 return users
51
52
52 - def get_user(self, user_id: int) -> User:
53 + def get_user(self, user_id: int) -> List[User] | None:
54 """
55 Get a user by ID.
56 :param user_id:
@@ -63,12 +64,12 @@ class SQliteDataManager(DataManagerInterface):
64 """
65 Add a user to the database.
66 """
66 - with self.get_db() as db:
67 - db.add(user)
68 - db.commit()
67 + with self.SessionFactory() as session:
68 + session.add(user)
69 + session.commit()
70
71 @property
71 - def movies(self) -> List[Movie]:
72 + def movies(self) -> list[Type[Movie]]:
73 """
74 Getter for movies.
75 Returns: a list of Movie objects
@@ -76,50 +77,41 @@ class SQliteDataManager(DataManagerInterface):
77 with self.SessionFactory() as db:
78 return db.query(Movie).options(joinedload(Movie.users)).all()
79
79 - def set_user_movies(self, user_id: int, movie_id: int, rating: float, user_rating: float = 0.0)\
80 + def set_user_movies(self, user_id: int, movie_id: int, user_rating: float = 0.0)\
81 -> None:
82 """
82 - Set (add) a movie to a user's list with a rating, or update the rating if it exists (self-contained session).
83 + Set (add) a movie to a user's list with a rating,
84 + either create a new association or update the rating if it exists (self-contained session).
85 """
84 - engine = self.engine
85 - with Session(engine) as db:
86 - user = db.query(User).filter_by(id=user_id).first()
87 - movie = db.query(Movie).filter_by(id=movie_id).first()
86
89 - if user and movie:
90 - existing_associations = db.query(UserMovie).filter_by(
87 + with self.SessionFactory() as session:
88 + user = session.query(User).filter_by(id=user_id).first()
89 + movie = session.query(Movie).filter_by(id=movie_id).first()
90 + print(f"user:{user}, movie:{movie}")
91 +
92 + if user is not None and movie is not None:
93 + existing_associations = session.query(UserMovie).filter_by(
94 user_id=user_id, movie_id=movie_id
95 ).all() #check if the association already exists
93 -
96 + print(f"existing_associations: {existing_associations}")
97 if existing_associations:
98 # existing association update
96 - db.execute(
97 - UserMovie.update().
98 - where(UserMovie.user_id == user_id).
99 - where(UserMovie.movie_id == movie_id).
100 - values(rating=rating, user_rating=user_rating)
99 + session.query(UserMovie).filter_by(user_id=user_id, movie_id=movie_id).update(
100 + {"user_rating": user_rating}
101 )
102 - if user_rating:
103 - print(f"Updated rating for user {user_id} and movie {movie_id} to "
104 - f"{rating} and also updated user rating to {user_rating}")
105 - else:
106 - print(f"Updated rating for user {user_id} and movie {movie_id} to {rating}")
102 else:
103 # create new association
109 - association = UserMovie(user_id=user_id, movie_id=movie_id, rating=rating,
104 + association = UserMovie(user_id=user_id, movie_id=movie_id,
105 user_rating=user_rating)
111 - db.add(association)
112 - print(f"Added movie {movie_id} to user {user_id} with rating {rating}")
106 + print(f"association: {association}")
107 + session.add(association)
108 + print(f"Added movie {movie_id} to user {user_id} with rating {user_rating}")
109 +
110 + session.commit() # Commit within the function
111
114 - db.commit() # Commit within the function
112
116 - elif user and not movie:
117 - try:
118 - self.set_movie(movie_title=movie.name)
119 - self.set_user_movies(user_id=user_id, movie_id=movie_id, rating=rating,
120 - user_rating=user_rating)
121 - except ValueError as e:
122 - print(f"Failed to add movie: {e}")
113 + elif user is not None and movie is None:
114 + print("Failed to add movie!")
115
116 else:
117 print("User or movie not found.")
@@ -130,51 +122,57 @@ class SQliteDataManager(DataManagerInterface):
122 Returns: A list of dictionaries, where each dictionary contains movie details
123 (name, director, year, poster) and the user's rating.
124 """
133 - with self.SessionFactory() as db:
134 - user = db.query(User).options(joinedload(User.movies)).filter_by(id=user_id).first()
135 - if user:
125 + with self.SessionFactory() as session:
126 + user_movies = session.query(UserMovie).filter_by(user_id=user_id).all()
127 + if user_movies:
128 movies_with_ratings = []
137 - for movie in user.movies:
138 - association = db.query(UserMovie).filter_by(user_id=user.id,
139 - movie_id=movie.id).first()
140 - if association:
129 + for association in user_movies:
130 + movie = session.query(Movie).filter_by(id=association.movie_id).first()
131 + if movie:
132 movies_with_ratings.append({
133 "id": movie.id,
134 "name": movie.name,
135 "director": movie.director,
136 "year": movie.year,
137 "poster": movie.poster,
147 - "rating": association.rating,
138 + "user_rating": association.user_rating,
139 })
140 return movies_with_ratings
141 return []
142
143
153 - def set_movie(self, movie_title: str) -> Movie:
144 + def set_movie(self, movie_title: str) -> Type[Movie] | Movie:
145 """
146 Add a new movie to the database.
147 + :param movie_title: The title of the movie to add.
148 """
157 - new_movie = OMDBClient().get_movie(title=movie_title)
158 - if new_movie is None:
159 - raise ValueError("Movie not found")
160 - movie = Movie(**new_movie)
161 - with self.SessionFactory() as db:
162 - db.add(movie)
163 - db.commit()
149 + with self.SessionFactory() as session:
150 + movie = session.query(Movie).filter_by(name=movie_title).first()
151 + if movie is not None:
152 + return movie
153 + new_movie = OMDBClient().get_movie(title=movie_title)
154 + if new_movie is None:
155 + raise ValueError("Movie not found")
156 + movie = Movie(**new_movie)
157 + session.add(movie)
158 + session.commit()
159 return movie
160
166 - def update_movie(self, movie_id: int, update_data: dict) -> Movie | None:
167 - session = self.SessionFactory()
168 - try:
161 + def update_movie(self, movie_id: int, update_data: dict) -> dict | None:
162 + with self.SessionFactory() as session:
163 movie = session.query(Movie).filter_by(id=movie_id).first()
164 if movie:
165 for key, value in update_data.items():
166 setattr(movie, key, value)
167 session.commit()
174 - return movie
168 + return {
169 + "id": movie.id,
170 + "name": movie.name,
171 + "director": movie.director,
172 + "year": movie.year,
173 + "poster": movie.poster
174 + }
175 return None
176 - finally:
177 - session.close()
176
177 def delete_movie(self, movie_id: int) -> bool:
178 """
@@ -186,13 +184,12 @@ class SQliteDataManager(DataManagerInterface):
184 Returns:
185 True if the movie was successfully deleted, False otherwise.
186 """
189 -
190 - with self.SessionFactory() as db:
191 - movie = db.query(Movie).options(joinedload(Movie.users)).filter_by(id=movie_id).first()
187 + with (self.SessionFactory() as db):
188 + movie = db.query(Movie).filter_by(id = movie_id).first()
189 if movie:
193 - # Remove the movie from all associated users' movie lists
194 - for user in movie.users:
195 - user.movies.remove(movie)
190 + # Safely clear all associations through the association object
191 + movie.user_movies.clear()
192 +
193 db.delete(movie)
194 db.commit()
195 return True
@@ -211,15 +208,12 @@ def main():
208 session.commit()
209
210 # Create some movies
214 - movie1 = Movie(name="The Matrix")
215 - movie2 = Movie(name="Inception")
216 - movie1 = data_manager.set_movie(movie1.name)
217 - movie2 = data_manager.set_movie(movie2.name)
218 - session.add_all([movie1, movie2])
219 - session.commit()
211 + movie1 = data_manager.set_movie("The Matrix")
212 + movie2 = data_manager.set_movie("Interstellar")
213
214 # Associate movies with users and assign ratings
222 - data_manager.set_user_movies(user1.id, movie1.id, 9.0,8.9)
215 + print(f"user1:{user1}, movie1:{movie1}")
216 + data_manager.set_user_movies(user1.id, movie1.id, 8.9)
217 print(data_manager.get_user_movies(user1.id))
218 data_manager.set_user_movies(user1.id, movie2.id, 8.5)
219 data_manager.set_user_movies(user2.id, movie2.id, 9.2)
@@ -233,18 +227,14 @@ def main():
227 print("All movies:", session.query(Movie).all())
228
229 # Example of updating a movie (use a new session)
236 - with data_manager.SessionFactory() as session_helper:
237 - updated_movie = data_manager.update_movie(movie1.id,
238 - {"name": "The Matrix Reloaded", "rating": 7.2})
239 - session_helper.add(updated_movie)
240 - session_helper.commit()
241 - print("Updated movie:", updated_movie)
230 + updated_movie = data_manager.update_movie(movie1.id,
231 + {"name": "The Matrix Reloaded", "user_rating":
232 + 7.2})
233 + print("Updated movie:", updated_movie)
234
235 # Example of deleting a movie (use a new session)
244 - with data_manager.SessionFactory() as session_helper:
245 - deleted = data_manager.delete_movie(movie1.id)
246 - session_helper.commit()
247 - print("Deleted movie1:", deleted)
236 + deleted = data_manager.delete_movie(movie1.id)
237 + print("Deleted movie1:", deleted)
238
239 print("All movies after deletion:", session.query(Movie).all())
240