Flask実践|おみくじアプリを作ってみよう【チャプター7-01】

一つ前のチャプターでは、エラーハンドリングとデバッグについて学習しました。
今回からはいよいよ、 実際に動くアプリ を開発していきましょう。
Chapter1:Flask入門編
Chapter2:Jinja2入門編
Chapter3:フィルター編
Chapter4:フォーム編
Chapter5:データベース編
Chapter6:エラーハンドリングとデバッグ編
Chapter7:アプリ開発編
・Chapter7-1:おみくじアプリを作ろう ◁今回はここ
・Chapter7-2:Blueprintを使おう
・Chapter7-3:メモ帳アプリを作ろう
・Chapter7-4:ToDoアプリを作ろう
これまでFlaskの基本的な使い方、テンプレートエンジンの使い方、フォームの仕組み、データベース操作など、段階的にFlaskの基礎を学んできました。
ここからはいよいよ、学んできた知識を使って実際にWebアプリケーションを作ってみましょう。
この章では、「おみくじアプリ」を題材にして、簡単なWebアプリケーションを作成します。
自分の名前を入力してボタンを押すと、ランダムに選ばれた運勢とコメントが表示されるアプリです。
このアプリを作成することで、以下のような内容を実践的に復習できます。
- Flaskの基本的なルーティングとテンプレートの使い方
- HTMLフォームから値を受け取って処理する方法
- Pythonの標準ライブラリ(random)との連携
- Jinja2テンプレートの継承や変数展開の活用
- CSSによる簡単なデザイン調整
Flaskの入門的な学習を終えた方にとって、今回のアプリ開発はとても良いステップになります。
難しそうに感じるかもしれませんが、一つ一つ丁寧に進めていけば大丈夫です。さあ、最初のアプリを一緒に作ってみましょう。
本記事は 有料記事(100円)ですが、現在は期間限定で無料公開中です。
おみくじアプリの概要とファイル構成
この章では、今回作成する「おみくじアプリ」の全体像と、構成されるファイルについて紹介します。
これからどのようなアプリを作るのか、そしてそれがどのようなファイルで構成されているのかを理解することで、学習をスムーズに進めることができます。
アプリの仕様と動作フロー
「おみくじアプリ」は、以下のような流れで動作する簡単なWebアプリです。
- ユーザーが自分の名前を入力する。
- ボタンを押すと、ランダムに運勢(大吉〜大凶)が選ばれる。
- 運勢に応じたコメントと一緒に、結果が画面に表示される。
シンプルですが、FlaskでWebアプリを作る際の基本的な流れがすべて詰まっています。
使用するファイルとフォルダ構成
今回のアプリでは、以下の5つのファイルを作成・使用します。以下のように保存してください。
omikuji_app/ ├── app.py # Flaskのメインプログラム ├── static/ │ └── style.css # デザイン(CSS)ファイル ├── templates/ │ ├── base.html # テンプレートの共通レイアウト │ ├── index.html # ユーザー入力フォームのページ │ └── result.html # おみくじ結果を表示するページ
app.py
FlaskアプリのメインとなるPythonファイルです。ルーティングやフォーム処理、テンプレートへのデータ渡しなど、アプリ全体の制御を行います。base.html
すべてのページに共通するHTMLの骨組み(テンプレート)です。タイトルやヘッダー、CSSの読み込みなどを含みます。index.html
ユーザーの名前入力フォームを表示するページです。base.html
を継承して作られています。result.html
入力された名前とランダムに選ばれたおみくじ結果を表示するページです。こちらもbase.html
を継承しています。style.css
アプリ全体の見た目を整えるCSSファイルです。文字のフォントやボタンのスタイルなどを指定します。
これらのファイルが連携することで、一つのWebアプリケーションとして動作します。それでは、次の章ではアプリの中心となるapp.py
の中身を詳しく見ていきましょう。
Flaskアプリのメイン処理|app.pyの全体像と解説
まずは、Flaskアプリの中心となるPythonコードを見てみましょう。
以下は、今回作る「おみくじアプリ」の中核となるapp.py
のコードです。
from flask import Flask, render_template, request import random app = Flask(__name__) # おみくじの結果とコメントの辞書を定義 OMIKUJI_COMMENTS = { "大吉": ["今日はすべてがうまくいく予感!", "何をやっても絶好調!"], "中吉": ["まずまず良い日になりそう。", "焦らず行動すれば吉。"], "小吉": ["ちょっとした幸せが訪れるかも。", "日常の中にチャンスあり。"], "吉": ["穏やかな一日になりそう。", "笑顔を忘れずに。"], "末吉": ["午後に運気アップの兆し!", "小さなことからコツコツと。"], "凶": ["慎重に行動を。トラブルには注意。", "体調管理に気をつけよう。"], "大凶": ["逆にレア運!悪い日こそ学びのチャンス。", "厄を落として運気上昇の始まり!"] } # ルートURLにアクセスした時の処理 @app.route('/', methods=['GET', 'POST']) def index(): if request.method == 'POST': # フォームから名前を取得 username = request.form.get('username') # おみくじの結果とコメントをランダムに選ぶ result = random.choice(list(OMIKUJI_COMMENTS.keys())) comment = random.choice(OMIKUJI_COMMENTS[result]) # 結果をテンプレートに渡して表示 return render_template('result.html', username=username, result=result, comment=comment) # 初回アクセス時は入力フォームを表示 return render_template('index.html') if __name__ == '__main__': app.run(debug=True)
このファイルがアプリ全体の心臓部です。フォームの処理、ランダム選択、結果の表示までを一括で行っています。
なお、以下の解説文内のリンクは、その内容の詳細をまとめた記事へ繋がっています。復習したい方はクリックして移動してください。
from flask import Flask, render_template, request
Flaskの基本機能とテンプレート表示、フォームデータ取得のためのモジュールをインポートします。app = Flask(__name__)
Flaskアプリのインスタンスを生成します。Flaskではこのようにしてアプリを作成します。OMIKUJI_COMMENTS
運勢とコメントのセットを辞書で定義しています。Pythonの辞書型 を用いています。@app.route('/', methods=['GET', 'POST'])
/
(トップページ)へのアクセスに対してGETとPOSTの両方のリクエストを処理します。(フォーム処理の基本)request.form.get('username')
ユーザーが入力した名前をHTMLフォームから取得します。random.choice()
Pythonの 標準ライブラリrandom
を使って、おみくじの結果とコメントをランダムに選びます。render_template()
HTMLテンプレートに値を渡して表示します。username
,result
,comment
がテンプレートに送られます。
base.html
:テンプレートの基本レイアウト
Flaskでは、複数のページに共通する部分(たとえばHTMLの<head>
や<header>
など)を一つのファイルにまとめることができます。
これを テンプレートの継承 といい、その基礎となるファイルが今回のbase.html
です。
以下は、今回使用するbase.html
の中身です。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>おみくじアプリ</title> <!-- 外部CSSファイルを読み込む --> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> </head> <body> <header> <h1>Flask おみくじアプリ</h1> </header> <main> {% block content %}{% endblock %} </main> </body> </html>
<!DOCTYPE html>
~<body>
一般的なHTML5のページ構造です。<head>
タグの中で文字コードやタイトルを指定し、<body>
タグの中にページの本体を記述します。<link rel="stylesheet" 中略 ">
静的ファイル(CSSや画像など)をstatic
フォルダに保存します。
詳細は CSSの学習記事 を参照ください。<header><h1>Flask おみくじアプリ</h1></header>
アプリの全ページに表示される共通の見出しです。どのページからアクセスしても一貫性のあるタイトルが表示されます。{% block content %}{% endblock %}
ここが テンプレート継承 の核となる部分です。具体的には、index.html
やresult.html
といった子テンプレートがこのblock
の中に自分の中身(フォームや結果表示)を挿入します。
index.htmlの作成|名前入力フォームの実装
index.html
は、おみくじアプリのスタート画面として、ユーザーが名前を入力するためのフォームを提供します。
このページはbase.html
を継承して作られており、見た目の統一感を保ちつつ、動的な内容を追加する構成になっています。
以下がその内容です。
{% extends 'base.html' %} {% block content %} <form method="POST" action="/"> <label for="username">あなたの名前:</label> <input type="text" name="username" id="username" required> <button type="submit">おみくじを引く!</button> </form> {% endblock %}
{% extends 'base.html' %}
base.html
を継承する宣言です。これにより、共通レイアウト(タイトルやヘッダーなど)がこのページにも反映されます。{% block content %}
~{% endblock %}
この部分がbase.html
で定義されていた{% block content %}
に挿入されます。つまり、main
タグの中にフォームが挿入される形になります。<form method="POST" action="/">
フォームの送信先と送信方法を指定しています。ここではPOSTメソッドを使って/
(トップページ)にデータを送信します。method="POST"
は、フォームのデータをHTTP POSTメソッドで送信することを意味します。action="/"
は、送信先のURLをトップページに指定していることを示します。これはapp.py
の@app.route('/', methods=['GET', 'POST'])
と対応しています。
<input type="text" name="username" id="username" required>
ユーザー名の入力欄です。name="username"
は、サーバー側でこの値を受け取るときの名前になります(request.form.get('username')
で取得)。required
属性があるため、ユーザーが空欄のまま送信することはできません。
<button type="submit">おみくじを引く!</button>
フォームの送信ボタンです。このボタンを押すと、入力された名前が送信され、サーバー側で処理されます。
このように、index.html
はアプリの出発点としてユーザーとの最初のインタラクションを担っています。
result.htmlの作成|結果ページへのデータ表示
result.html
はユーザーがフォームに名前を入力して送信したあとに表示されるページです。
ここではサーバー側(app.py
)で生成されたおみくじの結果と、それに対応するコメントを表示します。
このテンプレートもbase.html
を継承しており、共通のレイアウトの中に結果を表示する構造になっています。
以下がその中身です。
{% extends 'base.html' %} {% block content %} <p>{{ username }}さんの運勢は…</p> <h2>{{ result }}</h2> <p><em>{{ comment }}</em></p> <a href="/">もう一度ひく</a> {% endblock %}
{% extends 'base.html' %}
アプリ全体の共通レイアウトを継承する宣言です。これにより、HTMLの骨組みやCSSの読み込みなどが一貫して適用されます。{% block content %}
~{% endblock %}
結果表示に関する内容をこのブロック内に書いています。これがbase.html
のmain
タグの中に挿入されて表示されます。{{ username }}さんの運勢は…
ユーザーが入力した名前がここに表示されます。app.py
からテンプレートへ渡された変数username
を表示しています。<h2>{{ result }}</h2>
ランダムに選ばれた運勢(大吉・吉・中吉など)を大きな文字で表示しています。<p><em>{{ comment }}</em></p>
運勢に対応するコメントを斜体で表示しています。<em>
タグは「強調」の意味を持ち、読みやすさやデザインのアクセントとして活用できます。<a href="/">もう一度ひく</a>
トップページに戻って再びおみくじを引けるリンクです。href="/"
によりindex.html
を再度表示します。
このように、Flaskではテンプレート内で{{ }}
を使うことで、Pythonから渡されたデータをHTMLに埋め込むことができます。
これがFlaskと Jinja2 の大きな特徴です。
style.cssでアプリを整える|基本スタイルの適用法
Webアプリケーションでは、機能だけでなく「見た目」も重要です。特に初心者が作るアプリでも、CSSで少し手を加えるだけで印象がぐっと良くなります。
今回の「おみくじアプリ」では、以下のような簡単なCSSファイルを用意し、背景色や文字の配置、ボタンの見た目を整えています。
以下がその内容です。
body { font-family: sans-serif; text-align: center; background-color: #f9f9f9; } form { margin-top: 20px; } button { padding: 8px 16px; }
body
font-family: sans-serif;
サンセリフ体(ゴシック体)を指定しています。読みやすく、現代的な印象を与えます。text-align: center;
ページ全体のテキストを中央寄せにします。中央寄せはシンプルで、占いアプリのような内容と相性が良いです。background-color: #f9f9f9;
少しグレーがかった白色の背景にして、画面が真っ白にならないように工夫しています。
form
margin-top: 20px;
フォームの上部に20pxの余白を追加しています。これにより、ページのヘッダーとフォームがくっつかず、見やすくなります。
button
padding: 8px 16px;
ボタンの内側に余白を追加しています。これによりクリックしやすく、視認性も向上します。
まとめ
きちんと動作するアプリを作成できましたか?
まだ確認していない方は、ここで実際に動かしてみましょう。
今回の章では、これまでFlaskの基礎を学習してきた皆さんが、初めて実際にWebアプリを開発するというステップに挑戦しました。
最初のアプリ開発は、うまくいかないことやわからないことが多いかもしれません。
でも、実際に「動くものを作る」ことで得られる達成感はとても大きく、次へのモチベーションにもつながります。
ここまで作り上げたあなたは、もう「Flask初心者」ではありません。
次の章では、アプリをより効率よく構成するための「Blueprint」という設計手法を学んでいきます。
より複雑なアプリケーションへとステップアップする準備を、一緒に進めていきましょう。
FAQ|Flaskおみくじアプリの作り方
- Q1. Flaskで作ったアプリが「Method Not Allowed」エラーになるのはなぜ?
-
フォームでPOSTメソッドを使っている場合、対応するルート関数で
methods=['GET', 'POST']
が指定されていないとエラーになります。ルート定義を確認しましょう。
- Q2. HTMLテンプレートで{{ username }}が表示されないのはなぜ?
-
テンプレートに正しく変数が渡されていない可能性があります。
render_template()
でusername=username
のように明示的に渡しているかを確認しましょう。
- Q3. おみくじ結果が毎回同じになるのはどうして?
-
random.choice()
を使っていても、サーバーを再起動しない限り結果が固定されている場合は、関数の実行タイミングに問題があります。POSTリクエスト時にのみランダム処理を行うようにコードを見直してください。