quotes/app.py

148 lines
3.3 KiB
Python

import sqlite3, random
from flask import *
from pagination import Pagination
PER_PAGE = 10
app = Flask(__name__)
DATABASE = "quotes.db"
# util methods
def get_db():
db = getattr(g, "_database", None)
if db is None:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = sqlite3.Row
return db
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
@app.teardown_request
def teardown(exc):
db = getattr(g, "_database", None)
if db is not None:
db.close()
def url_for_other_page(page):
args = request.view_args.copy()
args["page"] = page
return url_for(request.endpoint, **args)
app.jinja_env.globals["url_for_other_page"] = url_for_other_page
# db helper methods
def get_post(id=1):
row = query_db("SELECT * FROM QUOTES WHERE ID=?", (id,))
if not row:
return False, []
return True, row[0]
def get_next_post_id():
return query_db("SELECT MAX(ID) FROM QUOTES", one=True)[0] + 1
def insert_new_post(id, text):
query_db("INSERT INTO QUOTES VALUES (?,?,?)", (id, text, 0))
get_db().commit()
def vote(id, d=1):
query_db("UPDATE QUOTES SET SCORE=SCORE+? WHERE ID=?", (d, id))
get_db().commit()
def count_all_quotes():
return query_db("SELECT COUNT(*) FROM QUOTES", one=True)[0]
def get_quotes_for_page(page, per_page, order_by="ID DESC"):
offset = count_all_quotes() - ((page - 1) * per_page) + 1
return query_db(
"SELECT * FROM QUOTES WHERE ID < ? ORDER BY {} LIMIT ?".format(order_by),
(offset, per_page),
)
# routes
@app.route("/", defaults={"page": 1})
@app.route("/page/<int:page>")
def home(page):
count = count_all_quotes()
quotes = get_quotes_for_page(page, PER_PAGE)
if not quotes and page != 1:
abort(404)
return render_template(
"index.html", pagination=Pagination(page, PER_PAGE, count), quotes=quotes
)
@app.route("/top", defaults={"page": 1})
@app.route("/top/<int:page>")
def top(page):
count = count_all_quotes()
quotes = get_quotes_for_page(page, PER_PAGE, order_by="SCORE DESC")
if not quotes and page != 1:
abort(404)
return render_template(
"top.html", pagination=Pagination(page, PER_PAGE, count), quotes=quotes
)
@app.route("/quote/<int:id>")
def quote(id):
ok, row = get_post(id)
if not ok:
return render_template("oops.html", id=id)
return render_template("quote.html", row=row)
@app.route("/quote/<int:id>/upvote")
def upvote(id):
vote(id, 1)
return redirect(url_for("quote", id=id), code=307)
@app.route("/quote/<int:id>/downvote")
def downvote(id):
vote(id, -1)
return redirect(url_for("quote", id=id), code=307)
@app.route("/quote/submit")
def submitform():
return render_template("submit.html")
@app.route("/submit", methods=["POST"])
def submit():
if request.form["quote"]:
nid = get_next_post_id()
insert_new_post(nid, request.form["quote"])
return redirect(url_for("quote", id=nid), code=302)
else:
return redirect(url_for("submitform"), code=307)
@app.route("/random")
def randomquote():
return redirect(url_for("quote", id=random.randint(1, get_next_post_id() - 1)))