エンジニアライフスタイルブログを運営しているミウラ(@miumiu06171)です。
普段はフリーランスでシステムエンジニアをしております。
今回は、Python入門者向けにWebアプリを作るFlaskの仕組み、使い方、Webアプリ作成までの流れを紹介していきます。
FlaskでWebアプリを作成するためにVisual Studio Code (VS Code) を使用しているため、同様に確認したい方は、こちらの記事でVS CodeでPythonの開発環境を構築してみてください。
PythonでWebアプリケーションを作るフレームワークの種類
PythonでWebアプリを簡単に作るには、フレームワークを使用するので、各フレームワークの特徴を解説していきます。
Flask(フラスク)
必要最低限の機能のみを備えているパッケージのため、軽量であることがメリットの一つです。
あとは、Pythonの文法を勉強していれば、追加で覚えることが少ないため、初心者向けのPythonフレームワークと言えます。
Django(ジャンゴ)
Webアプリ開発に必要な機能が一通り揃っていて、最もよく使われているPythonフレームワークです。
Djangoの使い方を知りたい方は、こちらの記事にまとめているので、ぜひ参照してみてください。
FastAPI(ファーストエーピーアイ)
Webアプリのレスポンスの速さ、コーディングの速さに定評があるフレームワークの一つです。
Tornado(トルネード)
高速処理が要求されるWebアプリに適しており、マルチタスクも可能なフレームワークです。
Bottle(ボトル)
Python標準ライブラリのみで作られているため、使いやすく、ソースコードの可読性もよいので、初心者向けのフレームワークです。
上記のフレームワークの中でも今回はFlaskについて、仕組み、使い方、Webアプリ作成までの流れを説明していきます。
Flaskの仕組み
ここでは、Flaskのおおまかなイメージをつかんでもらうため、FlaskでWebアプリを公開する仕組みについて図を使って解説していきます。
HTTPリクエストとHTTPレスポンス
まずは、Webアプリの基本的な仕組みをおさえましょう。
ユーザがブラウザ経由でサーバにHTTPリクエストを送ると、サーバがリクエストに応じたHTTPレスポンスを返します。
そして、HTTPレスポンスの情報をブラウザが読み取って画面上に表示します。
今説明してきたようにサーバ内のWebアプリ(Flask)がやることは、HTTPリクエストを受け取って、HTTPレスポンスを返すことが仕事なのです。
URLディスパッチ
次は、FlaskのURLディスパッチについて解説します。
そもそも「ディスパッチ」とは、「リクエストを受けた後、サーバを実行状態に遷移させて、処理を割り当てること」を言います。
上図では、ユーザから「https://sample.com/blog」にリクエストがあった場合にView1、「https://sample.com/list」にリクエストがあった場合にView2を表示するように処理を割り当てる例を図式化したものです。
View(ビュー)とは、後述するHTMLテンプレートファイル、モデル(Model)、静的ファイルなどを使って作成したレスポンスを指します。
HTMLテンプレートファイルとJinja2テンプレートエンジン
HTMLテンプレートファイルを入力としてJinja2テンプレートエンジンで解析・処理し、Viewとしてレスポンスを返します。
モデル(Model)とデータベース管理システム(RDBMS)
モデルでデータベースのテーブルを定義したり、逆にデータベースのテーブルから必要なデータを取り出したりできます。
データベースが何かわからない方は、こちらの記事を参照ください。
O/RマッパーとDBドライバ
O/Rマッパーは、Pythonとデータベース間の違いを吸収し、複数種類あるデータベースの操作の違いをユーザが意識することなく、簡単に使えるようにします。
DBドライバは、複数種類あるデータベースの各ドライバソフトになります。
Flaskを使って作成するWebアプリで採用するデータベースによって、ドライバソフトをWebサーバにインストールしておく必要があります。
また、O/RマッパーとDBドライバは、ユーザがインストールする必要がありますが、一度インストールすれば編集する必要はないものです。
静的ファイル(HTML/CSS/JavaScript/画像など)
静的ファイルは、あるHTTPリクエストのURLに対して、一意のレスポンスを返す場合に使われます。
Flaskチュートリアルとクイックスタート
Flask公式ページのチュートリアルをみたい方は、こちらを参照してください。
また、Flask公式ページのクイックスタートガイドについては、こちらに掲載されています。
本章以降では、上記チュートリアルやクイックスタートをベースにFlaskの使い方を丁寧に説明していきます。
Flask使い方基礎からWebアプリケーション作成までの流れ
Flaskの使い方の基礎からWebアプリケーション作成までの流れを解説していきます。
FlaskでHello Worldを表示
プログラミング初心者にはおなじみの「Hello World」を表示するプログラムをFlaskを使って作成してみましょう。
hello.pyの作成
Flaskで「Hello World」を表示するプログラムは、以下のとおりです。
1 2 3 4 5 6 7 |
from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "Hello, World!" |
ここでは、まずVSCodeを開き、上記プログラムをhello.pyとして作成してみてください。
Flaskサーバ起動(flask run)
hello.pyに「Hello World」を返すhello_world関数を定義できたら、Flaskサーバを起動してHTTPレスポンスが返ってくることを確認しましょう。
なお、PowerShellとコマンドプロンプトでFlaskサーバを起動するコマンドが異なるので、それぞれの場合のコマンドを紹介します。
PowerShellの場合
1 2 |
$env:FLASK_APP = "hello" flask run |
・コマンドプロンプトの場合
1 2 |
set FLASK_APP=hello flask run |
Flaskサーバが起動できたら、「http://127.0.0.1:5000/」にアクセスし、「Hello World」が表示されればオッケーです。
Flaskをデバッグモードに設定(FLASK_ENV)
Flaskをデバッグモードに設定すると、hello.pyファイルの更新がある都度、自動的にFlaskサーバも更新され、ブラウザの表示内容も更新されます。
デバッグモードに設定しないと、hello.pyファイルを更新するたび、「flask run」コマンドを実行し直す必要があります。
そのため、開発中はデバッグモードで使うことをおすすめします。
・PowerShellの場合
1 2 3 |
$env:FLASK_APP = "hello" $env:FLASK_ENV = "development" flask run |
・コマンドプロンプトの場合
1 2 3 |
set FLASK_APP=hello set FLASK_ENV=development flask run |
デバッグモードでFlaskサーバを起動できたら、hello.pyの出力文字列「Hello World」を編集し、リアルタイムでブラウザの表示内容が更新されたらオッケーです。
Flaskルーティング(Routing)
次は、Flaskのルーティング(Routing)について解説していきます。
「Hello World」のルーティング
前章で動作させた「Hello World」を返すhello.pyを見てください。
1 2 3 4 5 6 7 |
from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "Hello, World!" |
5行目の「@app.route(“/”)」の部分がルーティング設定になります。
ここでは、Flaskサーバのルート(/)にアクセスした場合、その下のhello_world関数を実行することを意味しています。
このルーティング設定により、Flaskサーバのルート(http://127.0.0.1:5000/)にアクセスすると、hello_world関数が実行され、return文に記述した「Hello World!」のレスポンスが返されます。
複数のルーティング
次は、Flaskサーバのルートにアクセスする単純なものだけでなく、複数のルーティングを定義した例を見ていきましよう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "Hello, World!" @app.route("/Miura") def hello_miura(): return "Hello, Miura!" @app.route("/Tanaka") def hello_tanaka(): return "Hello, Tanaka!" |
ここでは、以下の3つのルーティングを定義しています。
・「/」(5行目)
「http://127.0.0.1:5000/」にアクセスした場合
・「/Miura」(9行目)
「http://127.0.0.1:5000/Miura」にアクセスした場合
・「/Tanaka」(13行目)
「http://127.0.0.1:5000/Tanaka」にアクセスした場合
「Hello World!」、「Hello Miura!」、「Hello Tanaka!」のレスポンスを返す「hello_world」「hello_miura」「hello_tanaka」関数をそれぞれ定義しています。
関数名が重複するとエラーになるので、関数名は一意になるように注意してください。
引数を受け取って複数のルーティングをまとめる
次は、先程の「複数のルーティング」で使ったhello.pyの以下の9行目~15行目のプログラムをまとめる方法を紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "Hello, World!" @app.route("/Miura") def hello_miura(): return "Hello, Miura!" @app.route("/Tanaka") def hello_tanaka(): return "Hello, Tanaka!" |
なぜまとめるかというと。。。
「/Miura」、「/Tanaka」に加えて、佐藤さん、山田さん用に「/Sato」、「/Yamada」を追加しようと思ったときに、同じようなプログラムが増えてしまい、可読性も悪くなるためです。
そこで、共通化できる部分と可変な部分を見極めて、複数のルーティングをまとめることを考えます。
可変な部分は、下図に示すように名前部分が可変であることがわかります。
この名前部分をまとめると、下図のようにプログラムを関数一つにまとめることができます。
まとめた後のhello.pyのプログラムは、以下のとおりになります。
1 2 3 4 5 6 7 8 9 10 11 |
from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "<h1>Hello, World!</h1>" @app.route("/<name>") def hello_user(name): return f"Hello, {name}!" |
上記の9行目のように記述すると、URLの一部分(<name>)を変数として受け取ることができます。
また、10行目の関数引数にnameを指定することで、URLの一部分を関数の引数として受け取ることができます。
そして、11行目ではPythonの文法をしたがって受け取ったname引数を関数内で使用することができます。
最後にプログラムの内容がわかったところで、以下の3つにアクセスし、同じように動作するか確認してみましょう。
「http://127.0.0.1:5000/Miura」
「http://127.0.0.1:5000/Tanaka」
「http://127.0.0.1:5000/Sato」
「Miura」「Tanaka」「Sato」が関数引数として受け取り、ブラウザ上の名前が変わっていることが確認できればオッケーです。
FlaskのHTMLテンプレートファイル
FlaskでHTMLコードを返す方法
FlaskのHTMLテンプレートファイルを使ってレスポンスを返す前に、単純なHTMLを返すプログラムで動作を確認してみましょう。
1 2 3 4 5 6 7 |
from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "<h1>Hello, World!</h1>" |
前章の「Hello, World!」を返すプログラムに<h1>タグをつけることでHTMLをレスポンスとして返すことができます。
そして、「Hello, World!」のようにHTMLコードが短かければ問題ありませんが、Pythonファイル(hello.py)にHTMLコードも記述するとコード量が多く、PythonとHTMLのコードが混合するので、可読性が悪くなり、デバッグもしにくいというデメリットがあります。
これを解決するためにPythonとHTMLのコードを分けるHTMLテンプレートファイルを使う方法を次に紹介します。
FlaskでHTMLテンプレートファイルを読み込む方法
FlaskのHTMLテンプレートファイルを使うには、まず以下のようにtemplatesフォルダ内にHTMLテンプレートファイルを保存する必要があります。
【フォルダ構成例】
1 2 3 4 |
|- application |- hello.py |- templates |- hello.html |
フォルダ構成が整ったら、hello.pyからhello.htmlのHTMLテンプレートファイルを読み込むコードを書いていきましょう。
1 2 3 4 5 6 7 8 |
from flask import Flask from flask import render_template app = Flask(__name__) @app.route("/") def hello_world(): return render_template('hello.html') |
2行目は、HTMLテンプレートファイルを読み込むためのFlaskのrender_templateメソッドをインポートしています。
8行目は、先程のrender_templateメソッドに引数としてhello.html(HTMLテンプレートファイル)を指定しています。
これでPythonファイルからHTMLテンプレートファイルを読み込む処理はオッケーです。
次にhello.htmlに「Hello, World!」を表示するHTMLコードを示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>Hello, World!</h1> </body> </html> |
これでFlaskでHTMLテンプレートファイルを読み込む方法が理解できたかと思います。
FlaskのHTMLテンプレートファイルに変数の値を渡す方法
FlaskでHTMLテンプレートファイルを読み込めたところで、次はFlaskのプログラムで実践でも使われるPython側の変数の値をHTMLテンプレートファイルに渡して表示する方法をみていきましょう。
「複数のルーティングをまとめる」章のプログラムをベースとして、hello.py(Pythonファイル)の変数の値をhello.html(HTMLテンプレートファイル)に渡して表示するプログラムを作ります。
1 2 3 4 5 6 7 8 |
from flask import Flask from flask import render_template app = Flask(__name__) @app.route("/<name>") def hello_user(name): return render_template('hello.html', name=name) |
8行目のようにrender_templateメソッドの第二引数「name=name」を指定することで、第一引数「hello.html」に変数nameの値を渡すことができます。
初心者には「name=name」の左辺nameと右辺nameが何を意味しているかわかりにくいと思うので解説します。
右辺nameは、Pythonファイルで扱う変数を表し、前述してきたとおりここではルーティングのURLの一部を引数で受け取った値を指します。
左辺nameは、以下のようにHTMLテンプレートファイル内で扱う変数を表します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>Hello, {{name}}!</h1> </body> </html> |
左辺nameをHTMLテンプレートファイルで扱うためには、上記のようにJinja2テンプレートエンジンの文法にしたがって「 {{name}} 」と記述することで参照することができます。
ここまで出来たら、再度以下の3つにアクセスして動作を確認してみましょう。
「http://127.0.0.1:5000/Miura」
「http://127.0.0.1:5000/Tanaka」
「http://127.0.0.1:5000/Sato」
FlaskのHTMLテンプレートファイル(Jinja2テンプレートエンジン使用)
FlaskのHTMLテンプレートファイル内でJinja2テンプレートエンジンを使った記述を解説していきます。
FlaskのJinja2テンプレートエンジンとは
FlaskのJinja2テンプレートエンジンとは、HTMLテンプレートファイルとPythonから渡された変数などをもとにして、出力ファイルであるHTMLファイルを作る工程を自動化したソフトです。
前章でHTMLテンプレートファイル内で「 {{name}} 」のような記述することでPythonの変数の値を読み込んだが、この「{{ }}」の記述はJinja2テンプレートエンジンが処理可能な文法で記述されていました。
Jinja2テンプレートエンジンの詳細については、こちらの公式ドキュメントを参照してください。
次は、Pythonのリストや辞書型の変数を渡し、Jinja2テンプレートエンジンで処理する例を解説していきます。
リストをHTMLテンプレートファイルに渡すサンプルコード
リストをHTMLテンプレートファイルに渡すサンプルコードは、以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from flask import Flask from flask import render_template app = Flask(__name__) items = [ 'アイテム1', 'アイテム2', 'アイテム3', 'アイテム4', 'アイテム5', 'アイテム6', ] @app.route("/") def hello(): return render_template('hello.html', items=items) |
リストとしてitems変数を用意し、render_templateメソッドの第二引数にわたすことでHTMLテンプレートファイルにitems変数の値を渡しています。
items変数のリストデータをHTMLテンプレートファイルで処理するためには、以下のように記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <ul> {% for item in items %} <li>{{ item }}</li> {% endfor %} </ul> </body> </html> |
Pythonと似ていてfor文を使ってリストデータを繰り返し処理することができ、{{ }}はJinja2テンプレートエンジンで処理できる記述になります。
なお、Pythonと違ってfor文の終了行を示す「 {% endfor %} 」が明示的に必要なことに注意しましょう。
ここまで出来たら、「http://127.0.0.1:5000/」にアクセスし、以下のようにPythonのitems変数のリストデータが表示されていることを確認しましょう。
辞書型をHTMLテンプレートファイルに渡すサンプルコード
辞書型をHTMLテンプレートファイルに渡すサンプルコードは、以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from flask import Flask from flask import render_template app = Flask(__name__) di = [ {"name1": 'Miura', "name2": 'Junya'}, {"name1": 'Tanaka', "name2": 'Taro'}, ] @app.route("/") def hello(): return render_template('hello.html', di=di) |
辞書型データ2つをリストとしてもっているdi変数を、テンプレートファイルに渡しています。
辞書型のデータはどのようにHTMLテンプレートファイルで参照できるかみていきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <ul> {% for d in di %} <li>{{ d.name1 }} {{ d.name2 }}</li> {% endfor %} </ul> </body> </html> |
di変数は、リスト型でその中に辞書型データが2つ入っているので、まずfor文でリストを繰り返し処理し、for文内で「d.name1」「d.name2」のように辞書型のキー名を使って辞書型データを参照することができます。
ここまで出来たら、「http://127.0.0.1:5000/」にアクセスし、以下のようにPythonのdi変数内の辞書型データが表示されていることを確認しましょう。
まとめ
いかがでしたでしょうか。
PythonのFlask初心者向けに使い方の基礎からWebアプリケーション作成までの流れを紹介してきました。
実践編としてFlaskでデータベースと連携したWebアプリケーション作成する方法については、こちらの次回記事を参照してください。
FlaskやDjangoは、PythonでWebアプリを作成するときの代表的なライブラリのため、本記事で基本的な使い方を習得して頂ければ幸いです。
【関連記事】
【Python Flask入門】データベースと連携したWebアプリケーション作成
【Python Django入門】使い方からWebアプリ作成までの流れ