
今回は、川柳を表示するシンプルなWebページを作るよ。

まだ上五、中七、下五の登録などはできないけど、まずは、Pythonで作ったWebページが自分のブラウザに表示されるところまで進めよう!
Webサイトを見るとき、ブラウザの中に最初からページが入っているわけじゃないんだ。
ブラウザがWebサーバーへ「このページを見せて!」とお願いし、WebサーバーがHTMLなどのデータを返してくれる
かえってきたHTMLはとても見づらいので、人間がわかりやすいようにきれいに表示してるのは、ブラウザの役目。

今回登場する4つには、それぞれ別の役割があるよ。
| 名前 | 主な役割 | 今回担当すること |
|---|---|---|
| HTML | ページの内容と構造を作る | 見出し、説明文、川柳を書く |
| CSS | ページの見た目を整える | 色、文字の大きさ、余白を決める |
| Python | データを処理する | サイト名やメッセージを用意する |
| Flask | ブラウザとPython・HTMLをつなぐ | URLに合ったPythonの関数を動かし、HTMLを返す |
人間の顔にたとえると、HTMLの仕事は、お正月の福笑いみたいに、かおのパーツを置くところをざっくり設定する感じ。
CSSは、その顔にお化粧などをして、おしゃれしたりかわいくしたりする感じ
pythonやflaskの力で、その人を歌ったり踊ったりさせて、アイドルみたいに人をひきつけるサイトになっていくわけ。

Flaskは、ブラウザから来たお願いを受け取り、必要なPythonの処理とHTMLを結び付ける案内役なんだ。
FlaskはPythonのWebフレームワーク。PythonでWebサイトを作るために必要な機能をまとめて用意してくれる。
HTMLは、Webページに「これは大見出し」「これは文章」「これは画像」と、内容の意味や構造を付けるための言語なんだ。
HTMLは、次のように<と>で囲まれたタグを使って書くよ。
<h1>川柳ひろば</h1>
<p>みんなの川柳を楽しむサイトです。</p>
<button>川柳を作る</button>
HTMLファイルをそのまま見ると、英語や記号が混ざった文字に見えるよね。
ブラウザはタグの意味を読み取り、タグそのものは表示せず、次のようなWebページに変えてくれるよ。
See the Pen Untitled by ricky-sensei (@ricky-sensei) on CodePen.
CSSがない状態では、ブラウザが用意している基本の見た目で表示されるから、ぶっちゃけかなり味気ない感じのサイトになる。みんなが普段見ているおしゃれなサイトは、CSSの力を借りているわけだ

ブラウザにはいろんな種類があって、それぞれ特徴があるよ。

HTMLを表示する他にも、お気に入りのサイトをまとめておいたり、一度見たサイトを覚えておいたり、快適にインターネットを見ることができる機能がたくさんある。
多くのHTMLタグは、開始タグと終了タグで内容を挟むよ。
<h1>川柳ひろば</h1>
終了タグには/が付くよ。
タグにはそれぞれ役割があって、それぞれのタグの機能を組み合わせて使っていくよ
| タグ | 役割 |
|---|---|
<h1> |
ページで一番大きな見出し |
<p> |
文章のまとまり |
<button> |
ボタン |
<a> |
別のページへ移動するリンク |
<img> |
画像 |
HTMLタグには、次の2つのパターンがあるよ。
<h1>や<p>は、表示する文字を間に挟むから、開始タグと終了タグをセットで書くんだ。
<h1>川柳ひろば</h1>
<p>みんなの川柳を楽しむサイトです。</p>
一方、<img>や<br>のように、文字を間に挟まないタグもあるよ。これらは、終了タグを書かずに使うよ。
HTMLを勉強していくと出てくるから、今は覚えなくても全然OK
<img src="senryu.png" alt="川柳の画像">
<p>風吹けば<br>宿題ぜんぶ<br>飛んでいけ</p>
HTMLは、基本的にこういう形になっているよ。

VS Codeには、HTMLを素早く書くための**Emmet(エメット)**という機能が入っているよ。すべてのタグを手で書かなくても、Emmetに手伝ってもらえるんだ。
!でHTML全体を作ろうindex.htmlを開いて、何も書かれていない行に半角の!を入力してみよう。
!
!またはEmmet Abbreviationと書かれた候補が表示されたら、その候補を選んでEnterキーかTabキーを押してみてね。
!
↓ Emmetの候補を選ぶ
<!DOCTYPE html>
<html lang="en">
...
</html>
HTML全体のひな形が一度に作られるよ。<html lang="en">となっていたら、日本語のページでは<html lang="ja">へ変更しよう。
Tabキーで補完しようタグを1つ書きたいときは、<や>を全部手で入力しなくても大丈夫だよ。タグ名だけを入力して、Tabキーを押してみよう。
h1
↓ Tabキー
<h1></h1>
p
↓ Tabキー
<p></p>
開始タグと終了タグが自動で作られ、文字を入力する場所へカーソルが移動するよ。
候補が出ないときは、ファイル名が
.htmlで終わっているか確認してみよう。VS Codeの画面右下にHTMLと表示されているかも確認してね。
サーバーをわかりやすく説明すると、「24時間365日、みんなの要求に応え続けるために、電源つけっぱなしで働き続けているパソコン」のこと
例えばみんなのパソコンで素晴らしいウェブサイトをHTMLなどを使って作ったとして、それをどうやってみんなに見てもらうか考えてみよう。
まずはウェブサイトを見に来る人のパソコンから、みんなのパソコンの中のHTMLを見に来れるように設定しなくちゃいけないけど、それができたとして、ウェブサイトって基本いつでも見られるようにしなくちゃいけないよね。でもそれだと、みんなのパソコンを24時間つけっぱなしにしなくちゃいけない。実際、マインクラフトで友達とマルチプレイ(LANに公開)するときは、ワールドを作成するパソコンがサーバーとなっているから、そのパソコンでマイクラを終了したり電源を切ったりすると、他の参加者も接続が切れたりする。
でもウェブサイトの場合はそれだと困る。じゃあどうするかというと、24時間365日電源つけっぱなしの「サーバー」というパソコンに、HTMLを入れといて、いつでもアクセスできるようにしとけばいい。
実際に自分でウェブサイトを作るときは、まずは自分のパソコンで開発して、出来上がったらサーバーに公開することになるよ。
みんなが遊んでるオンラインゲームのサーバーは世界中のどこかにあるパソコンのことで、そのパソコンが頑張ってくれているから、世界中のプレイヤーと対戦できたりするわけ。

今回はflaskテストサーバーという、パソコン内(ローカル)の開発者用サーバーを使ってHTMLを見てみるよ。
2_flaskフォルダの中に、1_flask_web_pageフォルダを作る。
最初は、次のような構成にしよう。
1_flask_web_page
└── app.py
app.pyには、Flaskを動かすPythonコードを書いていくよ。
ファイル名を
flask.pyにすると、インストールしたFlaskと名前が重なってエラーの原因になる。今回はapp.pyという名前にしよう。
VS Codeで1_flask_web_pageフォルダを開き、ターミナルで次のコマンドを実行してみよう。
python -m pip install flask
インストールできたか確認しよう。
python -m pip show flask
Flaskの名前やバージョンが表示されたら、準備完了だよ!
app.pyへ次のコードを書く。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def show_index():
return "<h1>Hello, Flask!</h1>"
if __name__ == "__main__":
app.run(debug=True, port=8000)
ターミナルで次のコマンドを実行してみよう。
python app.py
次のような表示が出れば、Flaskのテストサーバーが起動できているよ。
* Serving Flask app 'app'
* Debug mode: on
* Running on http://127.0.0.1:8000
ブラウザで次のURLを開こう。
http://127.0.0.1:8000
画面に大きくHello, Flask!と表示されたら成功!
from flask import Flask
インストールしたflaskライブラリから、Flaskを使えるようにしているよ。
app = Flask(__name__)
この行で、Flaskアプリの本体を作ってappへ入れているんだ。
__name__は、FlaskがHTMLやCSSなどのファイルを探す場所を判断するために使われるよ。細かい仕組みは、今は覚えなくてOK!
@app.route("/")
def show_index():
@app.route("/")は、URLの/と、その下にあるshow_index()関数を結び付けているよ。
/はWebサイトの一番最初のページ、つまりトップページを表すんだ。
ブラウザが「/」をリクエスト
↓
show_index()を実行
このように、URLと関数を結び付ける設定をルートというよ。
return "<h1>Hello, Flask!</h1>"
関数が返した文字列は、Flaskからブラウザへのレスポンスになるんだ。
ブラウザは<h1>をHTMLの大見出しとして読み取り、大きな文字で表示してくれるよ。
ブラウザ → Flask → show_index() → HTMLをreturn → ブラウザ
if __name__ == "__main__":
app.run(debug=True, port=8000)
python app.pyでapp.pyを直接実行したとき、app.run()がFlaskのテストサーバーを起動するよ。
debug=True:コードを変更したときに自動で再起動し、エラーを確認しやすくするport=8000:8000番ポートでリクエストを待ち受けるif __name__ == "__main__":は、「このファイルが直接実行されたときだけ、その下の処理を動かす」という意味だよ。詳しい仕組みは、今は覚えなくてOK!
短いHTMLならPythonの文字列として書けるけれど、本物のWebページはもっと長くなるよね。
そこで、HTMLとCSSを役割ごとのファイルへ分けてみよう。
最終的なフォルダ構成は、次のようになるよ。
1_flask_web_page
├── app.py
├── templates
│ └── index.html
└── static
└── style.css
app.py:FlaskとPythonの処理templates/index.html:ページの内容と構造static/style.css:ページの見た目フォルダ名はtemplateではなくtemplates、staticはすべて小文字にしよう。
templatesフォルダを作り、その中にindex.htmlを作る。
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ site_name }}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<main class="card">
<p class="label">MY SENRYU SITE</p>
<h1>{{ site_name }}</h1>
<p class="description">{{ description }}</p>
<div class="senryu">
<p>古池や</p>
<p>リッキーやっぱり</p>
<p>イケメンだ</p>
</div>
<p class="message">{{ message }}</p>
</main>
</body>
</html>
{{ site_name }}などの二重波かっこは、Pythonから受け取ったデータをHTMLへ表示するための書き方だよ。
Pythonのsite_name
↓
HTMLの{{ site_name }}
↓
ブラウザに「川柳ひろば」と表示
この仕組みを提供しているものをJinja(ジンジャ)テンプレートというんだ。今回は、二重波かっこでデータを表示できることだけ覚えればOK!
staticフォルダを作り、その中にstyle.cssを作る。
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
display: grid;
place-items: center;
font-family: sans-serif;
color: #263238;
background: #e8f5e9;
}
.card {
width: min(90%, 640px);
padding: 48px 32px;
text-align: center;
background: #ffffff;
border: 4px solid #66bb6a;
border-radius: 24px;
box-shadow: 0 12px 30px rgba(38, 50, 56, 0.15);
}
.label {
margin: 0;
color: #388e3c;
font-size: 14px;
font-weight: bold;
letter-spacing: 0.15em;
}
h1 {
margin: 8px 0 12px;
font-size: 40px;
}
.description {
margin-bottom: 32px;
color: #607d8b;
}
.senryu {
padding: 24px;
background: #f1f8e9;
border-radius: 16px;
font-size: 28px;
font-weight: bold;
line-height: 1.5;
}
.senryu p {
margin: 4px;
}
.message {
margin: 28px 0 0;
color: #388e3c;
font-weight: bold;
}
HTMLの<link>に書いた次の部分が、FlaskへCSSファイルのURLを作ってもらう命令だよ。
{{ url_for('static', filename='style.css') }}
ブラウザはHTMLを受け取った後、このURLを使ってCSSも取得するんだ。
① ブラウザが「/」をリクエスト
② Flaskがindex.htmlを返す
③ ブラウザが「/static/style.css」をリクエスト
④ Flaskがstyle.cssを返す
⑤ ブラウザがHTMLにCSSを適用して表示する
app.pyを次のコードへ変更しよう。
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def show_index():
site_name = "川柳ひろば"
description = "みんなの言葉で、楽しい川柳を作ろう"
message = "PythonとFlaskで作ったよ!"
return render_template(
"index.html",
site_name=site_name,
description=description,
message=message,
)
if __name__ == "__main__":
app.run(debug=True, port=8000)
render_template()は、templatesフォルダにあるHTMLを読み込み、ブラウザへ返すための関数だよ。
return render_template(
"index.html",
site_name=site_name,
description=description,
message=message,
)
右側はPythonの変数、左側はHTMLで使う名前になっているよ。
Python HTML
site_name="川柳ひろば" → {{ site_name }}
description="みんなの…" → {{ description }}
message="Pythonと…" → {{ message }}
テストサーバーが動いている状態で、ブラウザを再読み込みしよう。
HTMLとCSSでデザインされた川柳ページが表示されたら完成だよ!
ここまでの処理を一つにつなげると、次のようになるよ。
① ブラウザで http://127.0.0.1:8000/ を開く
↓
② Flaskのテストサーバーが「/」へのリクエストを受け取る
↓
③ @app.route("/")と結び付いたshow_index()を実行する
↓
④ Pythonでsite_name、description、messageを用意する
↓
⑤ render_template()がindex.htmlへデータを渡す
↓
⑥ Flaskが完成したHTMLをブラウザへ返す
↓
⑦ ブラウザがstyle.cssも取得する
↓
⑧ HTMLにCSSを適用して画面を表示する
index.htmlに直接書かれている川柳を、自分で考えたものへ変更しよう。
<div class="senryu">
<p>ここに上五</p>
<p>ここに中七</p>
<p>ここに下五</p>
</div>
変更したら、ブラウザを再読み込みして確認してみよう。
style.cssの色を変更しよう。
変更しやすい場所はここ。
body {
background: #e8f5e9;
}
.card {
border: 4px solid #66bb6a;
}
好きな色へ変更して、自分のサイトらしい見た目にしてみよう。
app.pyの3つの変数を変更しよう。
site_name = "川柳ひろば"
description = "みんなの言葉で、楽しい川柳を作ろう"
message = "PythonとFlaskで作ったよ!"
Pythonの変数を変えると、HTMLの{{ site_name }}などの表示が変わるよ。実際に変更して確かめてみよう。
早く終わった人は、app.pyのif __name__ == "__main__":より上へ、次のルートを追加しよう。
@app.route("/about")
def show_about():
return "<h1>このサイトについて</h1><p>川柳を楽しむサイトです。</p>"
ブラウザで次のURLを開く。
http://127.0.0.1:8000/about
/と/aboutで別の関数が実行され、別のページが表示されるか確かめてみよう。
No module named 'flask'と表示されるFlaskが、今使っているPython環境にインストールされていないかもしれないよ。
python -m pip install flask
をもう一度実行してみよう。
TemplateNotFoundと表示される次を確認しよう。
templatesになっているかtemplatesの中にindex.htmlがあるかrender_template("index.html")の名前と一致しているかapp.pyを実行しているフォルダのすぐ下にtemplatesがあるか次を確認しよう。
staticになっているかstaticの中にstyle.cssがあるか<link>が正しく書かれているかAddress already in useと表示される別のプログラムが8000番ポートを使っているかもしれないよ。
先に起動したFlaskが別のターミナルに残っていないか確認しよう。それでも使えない場合は、先生の指示に従ってapp.pyのポート番号を変更してみよう。
if __name__ == "__main__":
app.run(debug=True, port=8001)
変更後、もう一度app.pyを実行してみよう。
python app.py
この場合は、ブラウザで次のURLを開く。
http://127.0.0.1:8001
授業の最後に、Flaskを実行しているターミナルを選び、Ctrl+Cを押す。
ターミナルへ文字を入力できる状態に戻ったら、テストサーバーは停止できているよ。
サーバーを停止した後にページを再読み込みすると、ブラウザはFlaskへ接続できなくなるよ。実際に確かめてみてね。
@app.route()でURLとPythonの関数を結び付けるrender_template()でHTMLテンプレートをブラウザへ返すstatic、HTMLはtemplatesフォルダへ置く次回は、HTMLフォームから送った句をFlaskで受け取るよ。
POSTで句をPythonのリストへ保存し、GETで画面に表示してみよう!