Flaskチュートリアル-Flaskでブログを作ってみる③

image Flaskチュートリアル

前回の記事

Flaskチュートリアル-Flaskでブログを作ってみる②
前回の記事データベースを構築するはじめに投稿やユーザー情報を保存しておくためのデータベースを構築していきます。今回制作するブログは簡易的なものなので次のような構成でテーブルを作っていきます。「BlogContent」テーブル・i...

トップページのプログラムを作成

トップページに記事一覧を表示するためのプログラムを書きます。

Flaskチュートリアル-Flaskでブログを作ってみる①
はじめにこのチュートリアルではPythonの軽量WebフレームワークであるFlaskを使ってブログを制作していきます。このチュートリアルで使用している環境OS:macOS Catalinaエディタ:AtomPython3.7SQlit...

でapp.pyに

Flask,render_template

だけ読み込ませているので新しく次のように書き足してください。

from flask import Flask,render_template,session,request,redirect,url_for
from models.database import Base,db_session
from models.models import BlogContent,Users

新しくインポートしたライブラリについて

session

FlaskでSessionを扱うためのライブラリです。

request

formに入力されたデータを読み取るためのライブラリです。

redirect

リダイレクトを簡単に行えるようにするライブラリです。

url_for

関数名を指定するとそれに対応するURLを返してくれるライブラリです。

例えば次のようなプログラムを組んで/homeにアクセスするすると/testpageにリダイレクトされて画面には”testpage”と表示されます。

@app.route("/testpage")
def test():
    return "testpage"

@app.route("/home")
def home
    return redirect(url_for("test"))

Base db_session

この2つはデータベースを操作するためのライブラリです。

BlogContent Users

モデルの設定データです。

記事を表示させるプログラム

必要なライブラリを読み込めたので記事を表示させるプログラムを書いていきます。

はじめに①で下のようなプログラムを書いていたと思いますが、必要ないので消してください。

@app.route("/template")
def template():
    return render_template("index.html",message="これはテンプレートです")

次にindex関数を次のように書き換えてください。

app.py

@app.route("/")
def index():
    if ("name" in session):
        if (not session["name"] == None):
            app.add_template_global(name="status",f="login")
    else:
        app.add_template_global(name="status",f="n")
    posts = db_session.query(BlogContent).order_by(BlogContent.id.desc())
    return render_template("index.html",posts=posts)

最初のif文ではログイン状態を確認してログインしていたらstatus関数にユーザー名を入れています。

add_template_globalを使うとメインテンプレートでも変数を利用できます。

次のpostsにはデータベースからBlogContentのデータを降順で入れています。

ここでプログラムを変えることで検索などの細かい設定をすることも可能です。

投稿データが入ったpostsはindex.html上のfor文で1件ずつ表示されます。

データベースに投稿データを入れてテストしてみる

記事一覧を表示できるようになったのでデータを入れて確かめてみます。

まだ投稿ページがないのでターミナルでプログラムを実行して直接入れます。

myblogフォルダに移動してPython3を開き次のように打ってください。

from models.database import db_session
from models.models import BlogContent
data = BlogContent("テスト","本文")
db_session.add(data)
db_session.commit()

これでデータを追加できたのでpython3 run.pyでサーバーを起動してブラウザで表示するとタイトルが表示されているはずです。

image

ログイン・ログアウトのプログラムを作る

次にログイン・ログアウトのプログラムを実装します。

app.pyに次のように追加してください

app.py


app.secret_key = "UfriMzp7nEQcKSf"

@app.route("/login")
def login():
    if ("name" in session):
        if (not session["name"] == None):
            return redirect(url_for("index"))
    else:
        app.add_template_global(name="status",f="n")
        return render_template("login.html")

@app.route("/login",methods=["post"])
def login_check():
    name = request.form["name"]
    password = request.form["password"]
    user = db_session.query(Users).filter_by(name = name,password = password).first()
    if user:
        session["name"] = name
        return redirect(url_for("index"))
    else:
        return render_template("login.html",message="NameまたはPasswordが違います")

@app.route("/logout")
def logout():
    session.pop("name",None)
    return redirect(url_for("index"))

app.secret_keyにはブラウザのセッションを使うためのキーを指定しています。適当に書き換えてください。

login関数ではログインページのテンプレートを返しています。

login_checkではフォームに入力されたユーザー情報が正しければセッションにユーザー名を書き込んでいます。

ログアウトではセッションのデータを消しています。

今回のログインシステムはセキュリティ的によろしくないので絶対に本番環境で使わないでください。

テスト

先程投稿データを入れたようにターミナルからユーザーデータを追加します。

from models.database import db_session
from models.models import Users
data = Users("{名前}","{パスワード(平文)}")
db_session.add(data)
db_session.commit()

サーバーを実行して/loginに追加した情報を入れることでログインできるはずです。

記事投稿ページのプログラムを作る

次に記事投稿ページにプログラムを実装します。

次のコードをapp.pyに追加してください。

@app.route("/add")
def add():
    if ("name" in session):
        if (not session["name"] == None):
            app.add_template_global(name="status",f="login")
            return render_template("add_post.html")
    else:
        return redirect(url_for("login"))

@app.route("/add",methods=["post"])
def add_post():
    if ("name" in session):
        if (not session["name"] == None):
            app.add_template_global(name="status",f="login")
            if (request.form["title"]) and (request.form["body"]):
                title = request.form["title"]
                body = request.form["body"]
                check_title = db_session.query(BlogContent).filter_by(title = title).first()
                if check_title:
                    message = title + "は既に使われています"
                    return render_template("add_post.html",message=message,title=title,body=body)
                else:
                    post_data = BlogContent(title,body)
                    db_session.add(post_data)
                    db_session.commit()
                    return redirect(url_for("post",title=title))
            else:
                if request.form["title"]:
                    return render_template("add_post.html",title=request.form["title"])
                if request.form["body"]:
                    return render_template("add_post.html",body=request.form["body"])
                if (not request.form["title"]) and (not request.form["body"]):
                    return redirect(url_for("add"))
    else:
        return redirect(url_for("login"))

addでは投稿フォームをログインしているユーザーに表示しています。

add_postはタイトルの被り等を確認した上でデータベースに追加しています。

サーバーを立ち上げてログインして状態で/addにアクセスすると投稿フォームが表示されるので適当に入力して見てください。

投稿を表示するプログラムをまだ実装していないので投稿後にエラーが出ると思いますが、トップページに戻ることで実際に投稿されているか確かめることができます。

記事を表示するプログラムを実装

投稿できるようになったので表示するプログラムを実装します。
app.py

@app.route("/post/<title>")
def post(title):
    if ("name" in session):
        if (not session["name"] == None):
            app.add_template_global(name="status",f="login")
    else:
        app.add_template_global(name="status",f="n")
    post_data = db_session.query(BlogContent).filter_by(title=title).first()
    if post_data:
        return render_template("post.html",post=post_data)
    else:
        return render_template("notfound.html")

@app.route("/post")
def post_none():
    return redirect(url_for("index"))

/post/タイトルにアクセスがあるとタイトルを取得してデータベースで検索・表示しています。

記事を編集・削除するプログラムを実装

@app.route("/edit/<title>")
def edit(title):
    if ("name" in session):
        if (not session["name"] == None):
            app.add_template_global(name="status",f="login")
            post_check = db_session.query(BlogContent).filter_by(title = title).first()
            if post_check:
                return render_template("edit_post.html",post=post_check)
            else:
                return redirect(url_for("index"))
    else:
        return redirect(url_for("login"))


@app.route("/edit/<title>",methods=["post"])
def edit_update(title):
    if ("name" in session):
        if (not session["name"] == None):
            app.add_template_global(name="status",f="login")
            post = db_session.query(BlogContent).filter_by(title = title).first()
            if post:
                if (request.form["title"]) and (request.form["body"]):
                    new_title = request.form["title"]
                    new_body = request.form["body"]
                    if (title == new_title):
                        post.body = new_body
                        db_session.commit()
                        return redirect(url_for("post",title=title))
                    else:
                        post_check = db_session.query(BlogContent).filter_by(title = new_title).first()
                        if post_check:
                            message = new_title+"は既に使われています"
                            return render_template("edit_post.html",post=post_check,message=message)
                        else:
                            post.title = new_title
                            post.body = new_body
                            db_session.commit()
                            return redirect(url_for("post",title=new_title))
                else:
                    return redirect(url_for("edit",title=title))
            else:
                return redirect(url_for("index"))
    else:
        return redirect(url_for("login"))


@app.route("/delete/<title>")
def delete(title):
    if ("name" in session):
        if (not session["name"] == None):
            app.add_template_global(name="status",f="login")
            post_check = db_session.query(BlogContent).filter_by(title = title).first()
            if post_check:
                post = db_session.query(BlogContent).filter_by(title = title).first()
                db_session.delete(post)
                db_session.commit()
                return redirect(url_for("index"))
            else:
                return redirect(url_for("index"))
    else:
        return redirect(url_for("login"))

編集用のプログラムは記事を投稿するプログラムの応用でできています。

最後にブログの指定&404エラーの設定

一通りのプログラムがかけたのでブログ名を指定して404エラーの場合に表示するページを設定します。

blog_name = "MasuBlog"

app.add_template_global(name="blog_name",f=blog_name)

@app.errorhandler(404)
def page_not_found(error):
    return render_template("notfound.html"), 404

完成

完成したのでサーバーを立ち上げていろいろ試してみてください。

最後の方説明が適当になっているのでなにかあればツイッターやコメント欄までお願いします。

最後まで読んでいただきありがとうございました。

ビスケットを送る

コメント

タイトルとURLをコピーしました