Skip to content

Commit 65182ff

Browse files
committed
Adding project1 - Books to the repository
1 parent 01d226e commit 65182ff

26 files changed

+5522
-0
lines changed
549 Bytes
Binary file not shown.

lecture2/application.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from flask import Flask, render_template
2+
3+
app = Flask(__name__)
4+
5+
@app.route("/")
6+
def index():
7+
return render_template("index.html")
8+
9+
@app.route("/<string:name>")
10+
def hello(name):
11+
name = name.capitalize()
12+
return f"<h1>Hello, {name}!</h1>"

lecture2/templates/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{% extends "layout.html" %}
2+
3+
{% block title %}
4+
Index
5+
{% endblock %}
6+
7+
{% block body %}
8+
9+
<h2>Index.html</h2>
10+
11+
{% endblock %}

lecture2/templates/layout.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>{% block title %} {% endblock %}</title>
5+
</head>
6+
<body>
7+
<h1>Hello World</h1>
8+
{% block body %} {% endblock %}
9+
</body>
10+
</html>

lecture3/create.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CREATE TABLE flights (
2+
id SERIAL PRIMARY KEY,
3+
origin VARCHAR NOT NULL,
4+
destination VARCHAR NOT NULL,
5+
duration INTEGER NOT NULL
6+
);

project1/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Project 1
2+
3+
Web Programming with Python and JavaScript
5.58 KB
Binary file not shown.
974 Bytes
Binary file not shown.

project1/application.py

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
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

Comments
 (0)