Flaskアプリケーションの構築と基本ルーティング
Flaskを使用して最小限のWebアプリケーションを作成します。以下のコードは、Flaskインスタンスの生成と基本的なルート定義を示しています。
from flask import Flask
web_app = Flask(__name__)
@web_app.route('/greeting')
def display_greeting():
return 'こんにちは、Flaskの世界へ!'
開発サーバーの起動とデバッグモード
Flaskの開発サーバーを起動するには、環境変数を設定してコマンドラインから実行する方法と、スクリプト内で直接実行する方法があります。開発中はコードの変更を自動的に検知してサーバーを再起動するデバッグモードを有効にすると効率的です。
from flask import Flask
web_app = Flask(__name__)
@web_app.route('/greeting')
def display_greeting():
return 'こんにちは、Flaskの世界へ!'
if __name__ == '__main__':
# デバッグモードを有効にしてサーバーを起動
web_app.run(debug=True, host='127.0.0.1', port=5000)
URL変数とデータ型の検証
URLパス内に動的な変数を埋め込むことができます。Flaskは正規表現を用いてURLをマッチングし、指定されたデータ型に変換します。型が一致しない場合は404エラーとなります。
# デフォルトは文字列型(スラッシュを含まない)
@web_app.route('/member/')
def get_member(member_id):
return f'メンバーID: {member_id}'
# 整数型への型変換
@web_app.route('/product/')
def get_product(product_id):
return f'商品ID: {product_id} (型: {type(product_id).__name__})'
# 複数の変数を組み合わせる
@web_app.route('/employee//')
def get_employee(dept, emp_id):
return f'部署: {dept}, 社員番号: {emp_id}'
URLの末尾スラッシュとリダイレクトの厳密な挙動
FlaskはURLの末尾スラッシュ(/)に対して厳密なルールを適用します。
- 末尾スラッシュが定義されているルート(例:
/articles/): スラッシュなし(/articles)でアクセスされた場合、サーバーは自動的にスラッシュ付きのURLへ301リダイレクトを行います。 - 末尾スラッシュが定義されていないルート(例:
/dashboard): スラッシュあり(/dashboard/)でアクセスされた場合、404 Not Foundエラーを返します。
この挙動は、ブラウザのキャッシュや相対パスの解決に影響を与えるため、ルート定義時には一貫性を持たせることが重要です。また、redirect()関数を使用することで、任意のURLへ明示的にリダイレクトさせることも可能です。
URLの動的生成(url_for)
ハードコードされたURLの代わりに、url_for()関数を使用してエンドポイント名からURLを動的に生成します。これにより、ルート定義が変更されてもリンク切れを防ぐことができます。
from flask import url_for
@web_app.route('/context')
def show_context():
# エンドポイント名と引数からURLを生成
target_url = url_for('get_product', product_id=42)
return f'生成されたURL: {target_url}'
HTTPメソッドの処理(GETとPOST)
デフォルトではルートはGETリクエストのみを受け付けます。POSTリクエストなどを許可するには、methods引数を使用します。リクエストオブジェクトを通じて、メソッドの種類や送信されたデータを取得できます。
from flask import request
@web_app.route('/api/records', methods=['GET', 'POST'])
def handle_records():
if request.method == 'POST':
# POSTデータの取得(フォームデータまたはJSON)
user_name = request.form.get('user_name')
user_age = request.form.get('user_age')
return f'登録完了 - 名前: {user_name}, 年齢: {user_age}'
# GETリクエストの場合
search_query = request.args.get('query', default='', type=str)
return f'検索クエリ: {search_query}'
ディレクトリ構造とファイル命名規則
Flaskは特定のディレクトリ構造を自動的に認識します。
- templates: HTMLテンプレートファイルを配置するディレクトリ。
render_template()関数を使用してレンダリングします。 - static: CSS、JavaScript、画像などの静的ファイルを配置するディレクトリ。HTML内では
url_for('static', filename='...')を使用して参照します。
Cookieとセッションの管理
クライアント側にデータを保存するCookieと、サーバー側で状態を管理するセッションの扱い方を説明します。セッションを使用するには、secret_keyの設定が必須です。
from flask import make_response, session, redirect, url_for
import os
# セッション暗号化のためのシークレットキー設定
web_app.secret_key = os.urandom(24)
@web_app.route('/set_preference')
def set_preference():
response = make_response('UIテーマを設定しました')
response.set_cookie('ui_theme', 'dark_mode')
return response
@web_app.route('/get_preference')
def get_preference():
theme = request.cookies.get('ui_theme', 'light_mode')
return f'現在のテーマ: {theme}'
@web_app.route('/login', methods=['POST'])
def login_user():
session['current_user'] = request.form.get('username')
return redirect(url_for('show_profile'))
@web_app.route('/profile')
def show_profile():
user = session.get('current_user', 'ゲスト')
return f'ようこそ、{user}さん'
フラッシュメッセージによるフィードバック
リダイレクトを挟んでユーザーに一度だけメッセージを表示させる「フラッシュメッセージ」機能です。カテゴリを指定して、テンプレート側でフィルタリングして表示できます。
from flask import flash, render_template
@web_app.route('/submit_data', methods=['POST'])
def submit_data():
data = request.form.get('input_data')
if not data:
flash('データが入力されていません。', 'error')
else:
flash('データが正常に保存されました。', 'success')
return redirect(url_for('index'))
@web_app.route('/')
def index():
return render_template('index.html')
アプリケーションロギング
Flaskは標準のPythonロギング機能と統合されています。アプリケーションの動作状況やエラーを記録するためにapp.loggerを使用します。
import logging
# ロギングレベルの設定
logging.basicConfig(level=logging.INFO)
web_app.logger.setLevel(logging.INFO)
@web_app.route('/compute')
def compute_value():
web_app.logger.info('計算エンドポイントが呼び出されました')
try:
result = 100 / 5
web_app.logger.info(f'計算結果: {result}')
return '計算成功'
except Exception as e:
web_app.logger.error(f'計算エラーが発生: {str(e)}')
return '内部エラー', 500