Python

【Flask入門2】投稿の表示からテンプレート拡張まで【Python】

Flask 入門 Python テンプレート拡張

 

※この記事は、Flask入門「パート1」からの続きになっています。パート1に引き続き、簡易版Twitterを作成していきます。

 

パート1を先に読んでおくことを、おすすめしますm(_ _)m

Flask 入門 Python ルーティング render_template
【Flask入門1】環境構築・ルーティング・render_templateまで【Python】『Pythonを使ってWebアプリケーションを作成したいな...。』『pythonのフレームワークFlaskを使ってWebアプリを作成したいな...。』このような悩みを解決する記事になっています。...

 

【Flask入門】投稿を表示してみよう

 

Flask入門のパート1に引き続き、簡易版Twitterを作成していきます。

前回までで、トップページに”Hello World!”を表示できる状態になっているはずなので、擬似投稿を表示してみたいと思います。

 

まず、hello.pyのルーティング前に、下記のような「擬似投稿」を記述しておきます。

#app = Flask(__name__)後に記述

posts = [
    {
        'username': 'Hayato',
        'title': 'First Post',
        'content': '初めての投稿をしたよ!',
        'date_posted': '2019/09/03' 
    },
    {
        'username': 'Hayatasu',
        'title': 'Second Post',
        'content': 'はやたすはマイクロツイッターを作成してみるよ!',
        'date_posted': '2019/09/04' 
    }
]

#@app.route('/')前に記述

こんな感じで、ユーザー名、タイトル、本文、投稿日のデータを作成しておきます。

 

そうしたら、いま擬似的に作成した投稿は、トップ画面(‘/’)で表示したい内容なので、下記のような変更も必要になってきます。

return render_template('home.html', posts=posts)

トップページに投稿を表示したいので、render_templateの引数にpostsを渡してあげます。

 

すべて合わせると、”hello.py”が下記のようになるはずです。

from flask import Flask, render_template
app = Flask(__name__)

posts = [
    {
        'username': 'Hayato',
        'title': 'First Post',
        'content': '初めての投稿をしたよ!',
        'date_posted': '2019/09/03'
    },
    {
        'username': 'Hayatasu',
        'title': 'Second Post',
        'content': 'はやたすはマイクロツイッターを作成してみるよ!',
        'date_posted': '2019/09/04'
    }
]

@app.route('/')
@app.route('/home')
def home():
    return render_template('home.html', posts=posts)

@app.route('/about')
def about():
    return render_template('about.html')


def main():
    app.debug = True
    app.run()

if __name__ == '__main__':
    main()

これでPythonからHTMLを呼び出すときに、自作した投稿データも表示できるようになりました。

 

でも、マークアップ側(HTML側)のコードが、まだ何も変わっていないですよね。

HTMLをいじってあげないと、目に見える部分は変わってきません。サーバーサイドだけでなく、フロント側の編集もやってあげましょう。

 

トップページの編集なので、home.htmlを開いてあげれば良さそうです。

記述するコードはこんな感じです。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title></title>
    </head>
    <body>
        <h1>Hello World!</h1>
        {% for post in posts %}
            <h2>{{ post.title }}</h2>
            <p>{{ post.title }}</p>
            <p>{{ post.username }} ( {{ post.date_posted }} )</p>
        {% endfor %}
    </body>
</html>

増えた部分は、”Hello World!”の下にある5行です。

postsの中には、先ほど書いた擬似投稿のリストが入っているので、for文で取り出してあげて、中身の部分を<h2>や<p>で囲っている感じですね。

 

render_templateの引数に渡してあげた変数たちは、”{{ }}”を使って囲ってあげれば使えるようになります。

 

完成図

Flask 擬似投稿

run server(python hello.pyで実行)してあげると上の画像のように、あらかじめ書いておいた擬似投稿がしっかりと表示されているかと思います。

 

これで少しTwitterっぽくなってきましたね。

 

【Flask入門】ページのタイトルを表示してみよう

 

次に、ページのタイトルを表示していきましょう。

いまページのタイトル部分は、ローカルサーバーのアドレスが書かれており、これでは何のWebアプリなのか分からない状態です。

Flask title

そこで、何のWebアプリなのか分かるように、ページのタイトルを付けてあげます。

タイトルは何でも良いですが、今回は下記のような名前にします。

  • トップ画面 : Micro_Twitter
  • このページについて : Micro_Twitter – About

 

HTMLのタイトルタグの部分に、「自分が決めたタイトル」を書いてあげれば完了ですね。

 

home.html(トップ画面)

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Micro Twitter</title>
    </head>
    <body>
        <h1>Hello World!</h1>
        {% for post in posts %}
            <h2>{{ post.title }}</h2>
            <p>{{ post.title }}</p>
            <p>{{ post.username }} ( {{ post.date_posted }} )</p>
        {% endfor %}
    </body>
</html>

 

about.html(このサイトについて)

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Micro Twitter - About</title>
    </head>
    <body>
        <h1>About us!</h1>
    </body>
</html>

 

こんな感じで、HTML側でタイトルを書いてあげれば、これだけで完了です。

でも、いちいちページごとに「これは何のページかな〜」って判断して、個別にタイトルタグに書いていくのは少しメンドイです。

どうせなら、同じような記述を流用できた方が、後々のコード回収なんかもラクになります。

 

なので、「HTML側では同じコードにしつつ、タイトルはPythonコードから適したものを渡す」ようにします。

 

HTML側の改修(home.htmlとabout.html)

#<meta>の下に書く
        {% if title %}
            <title>Micro Twitter - {{ title }}</title>
        {% else %}
            <title>Micro Twitter</title>
        {% endif %}
#</head>の上に書く

上記のように、書きます。

少し解説を加えると、「もしタイトルを与えていたら、”Micro Twitter – 自分の付けたタイトル”を表示」するというコードになっています。

逆(else)の場合には、”Micro Twitter”だけを表示するようになっています。

 

あとは、Python側でtitleを投げてあげれば良いのですが、どこに書くのか分かりますよね?

HTML側で”{{ }}”を使ってPythonで書いていたモノを使うには、postsのときと同じで、「render_templateの引数に渡してあげればOK」です。

 

トップ画面(home.html)は、Micro Twitterのママで良いので、タイトルを与える必要はありません。

「このページについて」の画面では、”Micro Twitter – About”としたいので、render_templateの引数で渡してあげます。

#def about():の下に書く
    return render_template('about.html', title='About')

こうしてあげると、”if title = True”(タイトルが存在するのでTrue)になるので、”Micro Twitter – {{ title }}”が使えるようになり、title = Aboutが入って目的のタイトルに仕上がります。

 

これでタイトル部分が完成しました(`・ω・´)!

 

【Flask入門】「テンプレート拡張」を使って重複している記述をなくす

 

ここまでのHTMLファイルを一度確認してみると、「投稿部分以外の記述以外、ほぼ同じである」ことに気がつくのではないでしょうか。

home.html

Flask home.html

 

about.html

Flask about.html

※about.htmlは、home.htmlと比較しやすいよう同じ行数するために、あえて改行してあります。

 

2つを見比べてもらえると分かりますが、投稿部分を除けばほとんど一緒ですよね。

このように何回も同じくだりを書くのはメンドイし、コードとしても微妙です。

 

冗長性を解決するには、「テンプレート拡張」を使ってあげればOKです。

Djangoでも同じ仕様でHTMLの冗長性を取り除けるので、PythonでWebアプリを作るなら必須の知識です。

 

テンプレート拡張を使うには、下記の手順でおこなっていきます。

  1. 共通部分を記述するHTML(index.html)を作成する
  2. home.htmlを編集する
  3. about.htmlを編集する

この手順でテンプレート拡張していきます。

 

テンプレート拡張のイメージ図

Flask テンプレート拡張 イメージ
テンプレート拡張のイメージ図は、こんな感じでして、共通部分をindex.htmlで記述しておき、独自の部分だけをそれぞれで書くイメージになります。

 

共通部分を記述するHTML(index.html)を作成する

 

index.htmlファイルを作成し、下記のコードを書いていきます。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    {% if title %}
        <title>Micro Twitter - {{ title }}</title>
    {% else %}
        <title>Micro Twitter</title>
    {% endif %}
</head>

<body>
    {% block content %}

    {% endblock %}
</body>

</html>

ポイントはblock contentの部分で、のちのちhome.htmlとabout.htmlで同じような記述をすることで、テンプレート拡張を可能にしていきます。

 

home.htmlを編集する

 

次に、home.htmlを編集していきます。

今まで書いていたコードは割と消してしまって良くて、代わりに下記のようなコードを記述します。

{% extends "index.html" %}
{% block content %}
    {% for post in posts %}
        <h2>{{ post.title }}</h2>
        <p>{{ post.username }} {{ post.date_posted }}</p>
        <p>{{ post.content }}</p>
    {% endfor %}
{% endblock content %}

一行目でテンプレート拡張で使う、元になるHTMlファイルをentendsしてあげて、2行目以降にblock contentで囲まれた独自部分を記述します。

 

イメージとしては、「index.htmlの”block content内”に、home.htmlの”block content内”の記述が入った感じ」です。

 

about.htmlを編集する

 

最後にabout.htmlを編集していきます。home.htmlのときと同じく、下記のような記述をすればOKです。

{% extends "index.html" %}
{% block content %}
    <h1>About us</h1>
{% endblock content %}

about.htmlの中は、たったこれだけの記述でOKになりました。

 

これでテンプレート拡張の導入が完了しました。

実際に、run server(python hello.pyを実行)してみると、今までどおり正常に動作するはずです。

 

テンプレート拡張を用いてフロントのコードを記述しておくと、これからCSSを当てていったり、ページ数が増えたりしても、いちから書かなくてよくなりますよね。

 

この記事は、ここまでの内容でいったん終わります。

次からは、フロント部分を少しイジりつつ、Flaskを使った簡易版ツイッターを作成していきます。