1
+ import os
2
+
3
+ import json
4
+
5
+ from flask import Flask , session , render_template , request , jsonify
6
+ from flask_session import Session
7
+ from sqlalchemy import create_engine
8
+ from sqlalchemy .orm import scoped_session , sessionmaker
9
+
10
+ from classes import User , Book
11
+
12
+ import requests
13
+
14
+ app = Flask (__name__ )
15
+
16
+ # Check for environment variable
17
+ if not os .getenv ("DATABASE_URL" ):
18
+ raise RuntimeError ("DATABASE_URL is not set" )
19
+
20
+ # Configure session to use filesystem
21
+ app .config ["SESSION_PERMANENT" ] = False
22
+ app .config ["SESSION_TYPE" ] = "filesystem"
23
+ Session (app )
24
+
25
+ # Set up database
26
+ engine = create_engine (os .getenv ("DATABASE_URL" ))
27
+ db = scoped_session (sessionmaker (bind = engine ))
28
+
29
+
30
+ @app .route ("/" )
31
+ def index ():
32
+ if session ["user" ] is None :
33
+ return login ()
34
+ else :
35
+ return render_template ("index.html" )
36
+
37
+
38
+ @app .route ("/login" , methods = ["GET" , "POST" ])
39
+ def login ():
40
+
41
+ if request .method == "POST" :
42
+
43
+ username = request .form .get ("username" )
44
+ password = request .form .get ("password" )
45
+ result = db .execute ("SELECT id, name, email, username, password FROM users WHERE username=:username AND password=:password" , {"username" : username , "password" : password }).fetchone ()
46
+ if result is None :
47
+ return render_template ("error.html" , message = "Username or password incorrect" )
48
+ else :
49
+ user = User (result .id , result .name , result .email , result .username , result .password )
50
+
51
+
52
+ if user :
53
+ session ["user" ] = user
54
+ return render_template ("index.html" )
55
+
56
+ return render_template ("login.html" )
57
+
58
+
59
+ @app .route ("/register" , methods = ["GET" , "POST" ])
60
+ def register ():
61
+ if request .method == 'GET' :
62
+ return render_template ("register.html" )
63
+ else :
64
+ name = request .form .get ("name" )
65
+ username = request .form .get ("username" )
66
+ email = request .form .get ("email" )
67
+ password = request .form .get ("password" )
68
+ db .execute ("INSERT INTO users(name, email, username, password) VALUES (:name, :email, :username, :password)" , {"name" : name , "email" : email , "username" : username , "password" : password })
69
+ db .commit ()
70
+ return render_template ("login.html" )
71
+
72
+
73
+ @app .route ("/layout" )
74
+ def layout ():
75
+ return render_template ("layout.html" )
76
+
77
+
78
+ @app .route ("/logout" )
79
+ def logout ():
80
+ """ Logout the user and clean the cache session"""
81
+ session ["user" ] = None
82
+ return render_template ("login.html" )
83
+
84
+
85
+ @app .route ("/books" , methods = ["GET" , "POST" ])
86
+ def books ():
87
+ if session ["user" ] is None :
88
+ return login ()
89
+
90
+ """ If the request is GET, render the page of search to the user with no books"""
91
+ if request .method == "GET" :
92
+ return render_template ("books.html" )
93
+ else :
94
+ """ If the request is POST, do the search with the text provided by the user"""
95
+ text = "%" + request .form .get ("search-text" )+ "%"
96
+ books = db .execute ("SELECT * FROM books WHERE (isbn LIKE :isbn OR title LIKE :title OR author LIKE :author OR year LIKE :year)" , {"isbn" :text , "title" :text , "author" :text , "year" :text }).fetchall ()
97
+ return render_template ("books.html" , books = books )
98
+
99
+
100
+ @app .route ("/details/<string:isbn>" , methods = ["GET" , "POST" ])
101
+ def details (isbn ):
102
+ if session ["user" ] is None :
103
+ return login ()
104
+ """ Give all the details about the book"""
105
+ book = Book ()
106
+
107
+ book .isbn , book .title , book .author , book .year , book .reviews_count , book .average_rating = db .execute ("SELECT isbn, title, author, year, reviews_count, average_rating FROM books WHERE isbn = :isbn" , {"isbn" : isbn }).fetchone ()
108
+
109
+ if book .average_rating == 0 or book .reviews_count == 0 :
110
+ book_aux = api_intern (isbn )
111
+
112
+ book .average_rating = book_aux ["books" ][0 ]["average_rating" ]
113
+ book .reviews_count = book_aux ["books" ][0 ]["reviews_count" ]
114
+ db .execute ("UPDATE books SET average_rating = :average_rating, reviews_count = :reviews_count WHERE isbn=:isbn" , {"isbn" : isbn , "average_rating" : float (book .average_rating ), "reviews_count" : int (book .reviews_count )})
115
+
116
+ db .commit ()
117
+ if request .method == "GET" :
118
+ return render_template ("details.html" , book = book )
119
+ else :
120
+ return "POST DETAILS"
121
+
122
+
123
+ @app .route ("/api/<string:isbn>" , methods = ["GET" ])
124
+ def api (isbn ):
125
+ """ Give all the details about the book"""
126
+ if request .method == "GET" :
127
+ res = db .execute ("SELECT title, author, year, isbn, reviews_count, average_rating FROM books WHERE isbn = :isbn" , {"isbn" : isbn }).fetchone ()
128
+ book = Book ()
129
+
130
+ if res is None :
131
+ return render_template ("error.html" , message = "404 book not found" ), 404
132
+
133
+ book .title , book .author , book .year , book .isbn , book .reviews_count , book .average_rating = res
134
+ if res .reviews_count == 0 or res .average_rating == 0 :
135
+ book_aux = api_intern (isbn )
136
+ book .average_rating = book_aux ["books" ][0 ]["average_rating" ]
137
+ book .reviews_count = book_aux ["books" ][0 ]["reviews_count" ]
138
+
139
+ response = {"title" : book .title , "author" : book .author , "year" : book .year , "isbn" : book .isbn , "review_count" : book .reviews_count , "average_score" : book .average_rating }
140
+ return jsonify (response )
141
+
142
+
143
+ def api_intern (isbn ):
144
+ """ Give all the details about the book"""
145
+ res = requests .get ("https://www.goodreads.com/book/review_counts.json" , params = {"key" : "tG3fNOMnNgw8HsbsI1Rhdg" , "isbns" : isbn })
146
+
147
+ return res .json ()
148
+
149
+
150
+ """ Route to submit and see the reviews from one book"""
151
+ @app .route ("/review/<string:isbn>" , methods = ["GET" , "POST" ])
152
+ def review (isbn ):
153
+ if session ["user" ] is None :
154
+ return login ()
155
+
156
+ """ Render form to the user submit a review """
157
+ book = db .execute ("SELECT * FROM books WHERE isbn= :isbn"
158
+ , {"isbn" : isbn }).fetchone ()
159
+ if request .method == "POST" :
160
+ review = request .form .get ("review" )
161
+ score = request .form .get ("score" )
162
+ """ Calculating new average rating and number of reviews from the book """
163
+ average_rating = (book .average_rating + float (score ))/ 2
164
+ reviews_count = book .reviews_count + 1
165
+ comments = db .execute ("SELECT * FROM reviews WHERE author_id= :author_id AND book_isbn= :book_isbn" , {"author_id" : session ["user" ].id , "book_isbn" : isbn }).fetchone ()
166
+
167
+ """ Checks if the user already made a comment to this book """
168
+ if comments is not None :
169
+ return render_template ("error.html" , message = "You already posted a comment to this book" )
170
+
171
+ db .execute ("INSERT INTO reviews(review, score, author_id, book_isbn) VALUES (:review, :score, :author_id, :book_isbn)" , {"review" : review , "score" : score , "author_id" : session ["user" ].id , "book_isbn" : isbn })
172
+ db .execute ("UPDATE books SET average_rating = :average_rating, reviews_count = :reviews_count WHERE isbn=:isbn" , {"isbn" : isbn , "average_rating" : average_rating , "reviews_count" : reviews_count })
173
+
174
+ db .commit ()
175
+
176
+ reviews = db .execute ("SELECT * FROM reviews WHERE book_isbn= :isbn"
177
+ , {"isbn" : isbn }).fetchall ()
178
+ return render_template ("review.html" , book = book , reviews = reviews )
0 commit comments