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