-
Notifications
You must be signed in to change notification settings - Fork 1
/
app.py
248 lines (217 loc) · 8.94 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
import os
from os import path
import requests
from flask import Flask, render_template, redirect, request, url_for, session, flash
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
from werkzeug.security import generate_password_hash, check_password_hash
if path.exists('env.py'):
import env
# Connection to Database
APP = Flask(__name__)
APP.config["MONGO_DBNAME"] = os.getenv('MONGODB_NAME')
APP.config["MONGO_URI"] = os.getenv('MONGO_URI')
APP.secret_key = os.getenv('SECRET_KEY')
mongo = PyMongo(APP)
# Collections
users_collection = mongo.db.users
favourites_collection = mongo.db.favourites
@APP.route('/')
@APP.route('/home')
def home():
'''
Home function, that holds the recent favourites to be displayed to users.
'''
return render_template("home.html", recents=favourites_collection.find())
@APP.route('/register', methods=['GET', 'POST'])
def register():
'''
Checks user is not already logged in, register if they are not present in db
'''
if 'user' in session:
flash('You are already signed in!')
return redirect(url_for('home'))
if request.method == 'POST':
form = request.form.to_dict()
# checking passwords match
if form['register_password'] == form['repeated_password']:
user = users_collection.find_one({"username": form['username']})
if user:
flash(f"{form['username']} already exists!")
return redirect(url_for('register'))
else:
# hashing password
hash_password = generate_password_hash(
form['register_password'])
users_collection.insert_one(
{
'username': form['username'],
'email': form['email'],
'password': hash_password,
'favourites': []
}
)
# Checking to see if users details have been saved
registered_user = users_collection.find_one({"username": form['username']})
if registered_user:
session['user'] = str(registered_user['_id'])
flash("Your account has been created!")
return redirect(url_for('home'))
else:
flash("There was an issue registering your account")
return redirect(url_for('register'))
else:
flash('Sorry your passwords do not match')
return redirect(url_for('register'))
return render_template('register.html')
@APP.route('/profile/<user>')
def profile(user):
'''
find user profile and return logged in profile and return favourites
pass user id to URL
'''
if 'user' in session:
user_favs_ids = users_collection.find_one({"_id": ObjectId(session['user'])},
{"favourites": 1})
user_favs = favourites_collection.find({"_id": {"$in": user_favs_ids["favourites"]}})
user = users_collection.find_one({"_id": ObjectId(session['user'])}, {"username": 1})
return render_template('profile.html', user_favs=user_favs, user_account=user)
flash("You must be logged in!")
return redirect(url_for('home'))
@APP.route('/login', methods=['GET'])
def login():
'''
Find user by username on form submission
'''
if 'user' in session:
find_user = users_collection.find_one({"_id": ObjectId(session["user"])}, {"_id": 1})
if find_user:
flash('You are already logged in!')
return redirect(url_for('profile', user=find_user['_id']))
else:
return render_template('login.html')
@APP.route('/auth', methods=['POST'])
def auth():
'''
Authenticate the user off their form input vs the users collection,
and their password vs the hashed password
'''
form = request.form.to_dict()
find_user = users_collection.find_one({"username": form['username']})
# Check for user in database
if find_user:
# If passwords match (hashed / real password)
if check_password_hash(find_user['password'], form['user_password']):
# Log user in (add to session)
session['user'] = str(find_user['_id'])
# If the user is admin redirect him to admin area for future release
if session['user'] == "admin":
return redirect(url_for('admin'))
else:
flash("You were logged in!")
return redirect(url_for('profile', user=find_user['_id']))
else:
flash("Wrong password or username!")
return redirect(url_for('login'))
else:
flash("You must be registered!")
return redirect(url_for('register'))
@APP.route('/logout')
def logout():
'''
Logout results in clearing the session and logging user out
'''
session.clear()
flash('You have been logged out!')
return redirect(url_for('home'))
@APP.route('/search', methods=['GET', 'POST'])
def search():
'''
On request, handles request from api,
returns movies and is appended to movie_results
'''
if request.method == 'POST':
search_term = request.form['search-term']
api_key = "3c0dea9f"
api = requests.get("http://www.omdbapi.com/?apiKey={}&s={}&page=1".format(api_key, search_term))
data = api.json()
movie_results = list()
if data['Response'] == 'False':
flash("No results found matching your search, be specific")
return render_template('search.html')
else:
for movies in data['Search']:
movie_results.append([movies['Title'], movies['Year'], movies['imdbID'], movies['Poster']])
return render_template('search.html', movie_results=movie_results)
else:
return render_template('search.html')
@APP.route('/add_favorite', methods=['POST'])
def add_favorite():
'''
Checks users favourites if does not exist,
add favourite to users collection
'''
if 'user' in session:
# Get all the oid from favourites using the imdbid
existing_fav_id = list(favourites_collection.find
({"imdbid": request.form.to_dict()["imdbid"]}, {"_id": 1}))
fav_id_arr = []
for fav in existing_fav_id:
fav_id_arr.append(fav["_id"])
# Compare the oids to the list of user favourite ids.
user_fav_id = users_collection.count_documents({"_id": ObjectId(session["user"]),
"favourites": {"$in": fav_id_arr}})
if user_fav_id > 0:
flash('Movie already added to your favourites!')
else:
# Save favourite to DB and store object ID
# into favourites of the currently logged in user
new_fav_id = favourites_collection.insert_one(request.form.to_dict()).inserted_id
users_collection.update_one({'_id': ObjectId(session['user'])},
{'$push': {'favourites': ObjectId(new_fav_id)}})
flash('Movie added to your favourites!')
return redirect(url_for('search'))
else:
flash('You must be logged in to add a favourite')
return render_template('login.html')
@APP.route('/delete_favorites/<favorites_id>')
def delete_favorites(favorites_id):
'''
Deleting a favourite from the users collection,
removing the movies from favs array
'''
if 'user' in session:
user_id = session['user']
users_collection.update_one({'_id': ObjectId(user_id)}, {'$pull': {"favourites": ObjectId(favorites_id)}})
# Delete the favourites document by favourite_id
favourites_collection.remove({'_id': ObjectId(favorites_id)})
flash('Movie removed from your list')
else:
flash('You must be logged in to remove this item')
return redirect(url_for('profile', user=user_id))
@APP.route('/edit', methods=['POST'])
def edit():
'''
Edit a favourite from the users collection
'''
if 'user' in session:
query = {'_id': ObjectId(request.form.get('_id'))}
projection = {'title': request.form.get('title'), 'year': request.form.get('year')}
# Edit the favourites document by favourite_id
favourites_collection.update_one(query, {'$set': projection})
flash('Movie details updated')
else:
flash('You must be logged in to remove this item')
return redirect(url_for('profile', user=session['user']))
@APP.errorhandler(404)
def response_404(exception):
"""When 404 is captured display custom 404.html page"""
return render_template('404.html', exception=exception)
@APP.errorhandler(500)
def response_500(exception):
"""When 500 is captured display custom 500.html page"""
return render_template('500.html', exception=exception)
if __name__ == '__main__':
APP.run(host=os.environ.get('IP'),
port=os.environ.get('PORT'),
debug=False)