From cafc557c6820e1808b1e4cf71f58ff99b97ca545 Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Sat, 28 Oct 2023 11:44:09 -0500 Subject: Add blueprint blog --- flaskr/views/auth.py | 2 +- flaskr/views/blog.py | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 flaskr/views/blog.py (limited to 'flaskr/views') diff --git a/flaskr/views/auth.py b/flaskr/views/auth.py index 3689eba..2dc32af 100644 --- a/flaskr/views/auth.py +++ b/flaskr/views/auth.py @@ -31,7 +31,7 @@ def register(): # (otherwise SQL injection vulnerability) db.execute( "INSERT INTO user (username, password) VALUES (?, ?)", - (username, generate_password_hash(password)), + (username, generate_password_hash(password)) ) db.commit() except db.IntegrityError: diff --git a/flaskr/views/blog.py b/flaskr/views/blog.py new file mode 100644 index 0000000..6f728ea --- /dev/null +++ b/flaskr/views/blog.py @@ -0,0 +1,104 @@ +from flask import ( + Blueprint, flash, g, redirect, render_template, request, url_for +) +from werkzeug.exceptions import abort + +from flaskr.views.auth import login_required +from flaskr.db import get_db + +# NOTE: no URL prefix +bp = Blueprint('blog', __name__) + + +@bp.route('/') +def index(): + db = get_db() + posts = db.execute( + 'SELECT p.id, title, body, created, author_id, username' + ' FROM post p JOIN user u ON p.author_id = u.id' + ' ORDER BY created DESC' + ).fetchall() + return render_template('blog/index.html', posts=posts) + + +@bp.route('/create', methods=('GET', 'POST')) +@login_required +def create(): + if request.method == 'POST': + title = request.form['title'] + body = request.form['body'] + error = None + + if not title: + error = 'Title is required.' + + if error is not None: + flash(error) + else: + db = get_db() + db.execute( + 'INSERT INTO post (title, body, author_id)' + ' VALUES (?, ?, ?)', + (title, body, g.user['id']) + ) + db.commit() + return redirect(url_for('blog.index')) + + return render_template('blog/create.html') + + +@bp.route('//update', methods=('GET', 'POST')) +@login_required +def update(id): + post = get_post(id) + + if request.method == 'POST': + title = request.form['title'] + body = request.form['body'] + error = None + + if not title: + error = 'Title is required.' + + if error is not None: + flash(error) + else: + db = get_db() + db.execute( + 'UPDATE post SET title = ?, body = ?' + ' WHERE id = ?', + (title, body, id) + ) + db.commit() + return redirect(url_for('blog.index')) + + return render_template('blog/update.html', post=post) + + +@bp.route('//delete', methods=('POST',)) +@login_required +def delete(id): + get_post(id) + db = get_db() + db.execute('DELETE FROM post WHERE id = ?', (id,)) + db.commit() + return redirect(url_for('blog.index')) + + +# Helper functions: + +def get_post(id, check_author=True): + post = get_db().execute( + 'SELECT p.id, title, body, created, author_id, username' + ' FROM post p JOIN user u ON p.author_id = u.id' + ' WHERE p.id = ?', + (id,) + ).fetchone() + + if post is None: + abort(404, f"Post id {id} doesn't exist.") + + if check_author and post['author_id'] != g.user['id']: + abort(403) + + return post -- cgit v1.2.3