flask/examples/tutorial/flaskr/blog.py

130 lines
3.4 KiB
Python
Raw Normal View History

import sqlite3
from typing import Optional, Union
from werkzeug.wrappers import Response
from flask import Blueprint
from flask import flash
from flask import g
from flask import redirect
from flask import render_template
from flask import request
from flask import url_for
2018-02-09 14:39:05 -08:00
from werkzeug.exceptions import abort
2023-11-09 09:20:27 -08:00
from .auth import login_required
from .db import get_db
2018-02-09 14:39:05 -08:00
bp = Blueprint("blog", __name__)
2018-02-09 14:39:05 -08:00
@bp.route("/")
def index() -> str:
2018-02-09 14:39:05 -08:00
"""Show all the posts, most recent first."""
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"
2018-02-09 14:39:05 -08:00
).fetchall()
return render_template("blog/index.html", posts=posts)
2018-02-09 14:39:05 -08:00
def get_post(id: int, check_author: bool = True) -> Optional[sqlite3.Row]:
2018-02-09 14:39:05 -08:00
"""Get a post and its author by id.
Checks that the id exists and optionally that the current user is
the author.
:param id: id of post to get
:param check_author: require the current user to be the author
:return: the post with author information
:raise 404: if a post with the given id doesn't exist
:raise 403: if the current user isn't the author
"""
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()
)
2018-02-09 14:39:05 -08:00
if post is None:
2020-04-04 09:43:06 -07:00
abort(404, f"Post id {id} doesn't exist.")
2018-02-09 14:39:05 -08:00
if check_author and post["author_id"] != g.user["id"]:
2018-02-09 14:39:05 -08:00
abort(403)
return post
@bp.route("/create", methods=("GET", "POST"))
2018-02-09 14:39:05 -08:00
@login_required
def create() -> Union[str, Response]:
2018-02-09 14:39:05 -08:00
"""Create a new post for the current user."""
if request.method == "POST":
title = request.form["title"]
body = request.form["body"]
2018-02-09 14:39:05 -08:00
error = None
if not title:
error = "Title is required."
2018-02-09 14:39:05 -08:00
if error is not None:
flash(error)
else:
db = get_db()
db.execute(
2019-06-01 09:22:20 -07:00
"INSERT INTO post (title, body, author_id) VALUES (?, ?, ?)",
(title, body, g.user["id"]),
2018-02-09 14:39:05 -08:00
)
db.commit()
return redirect(url_for("blog.index"))
2018-02-09 14:39:05 -08:00
return render_template("blog/create.html")
2018-02-09 14:39:05 -08:00
@bp.route("/<int:id>/update", methods=("GET", "POST"))
2018-02-09 14:39:05 -08:00
@login_required
def update(id: int) -> Union[str, Response]:
2018-02-09 14:39:05 -08:00
"""Update a post if the current user is the author."""
post = get_post(id)
if request.method == "POST":
title = request.form["title"]
body = request.form["body"]
2018-02-09 14:39:05 -08:00
error = None
if not title:
error = "Title is required."
2018-02-09 14:39:05 -08:00
if error is not None:
flash(error)
else:
db = get_db()
db.execute(
"UPDATE post SET title = ?, body = ? WHERE id = ?", (title, body, id)
2018-02-09 14:39:05 -08:00
)
db.commit()
return redirect(url_for("blog.index"))
2018-02-09 14:39:05 -08:00
return render_template("blog/update.html", post=post)
2018-02-09 14:39:05 -08:00
@bp.route("/<int:id>/delete", methods=("POST",))
2018-02-09 14:39:05 -08:00
@login_required
def delete(id: int) -> Union[str, Response]:
2018-02-09 14:39:05 -08:00
"""Delete a post.
Ensures that the post exists and that the logged in user is the
author of the post.
"""
get_post(id)
db = get_db()
db.execute("DELETE FROM post WHERE id = ?", (id,))
2018-02-09 14:39:05 -08:00
db.commit()
return redirect(url_for("blog.index"))