[Python]ロリポップのライトプランでFlask

雑記

(なんにも考えず)ロリポップのライトプランでサーバー借りてみた。そして何ができるか調べてみる。

そうか、Php,Ruby,Pythonが使えるのか。
https://lolipop.jp/manual/hp/cgi/

私の借りているlitxxxサーバーの場合は3.7が使えるそうです。

Pythonバージョン3.7
/usr/local/bin/python3.7

じゃあ、フレーワークは何にしよう。
Flaskは使えるのだろうか? →使えるようだ 以下のブログが参考になる。

https://kogyoyaro.com/lolipop-flask

まずはFlaskを学び始めることにしました。特に深く考えずに、評価の良い一番簡単そうな本を購入しました。素晴らしい本に感謝。本で学べるのはとてもありがたく、ブログをいくつも巡るよりも効率的だと思います。

ロリポップでデータベースを調べる

WEBアプリといえばやはりデータベースは必須だと思います。ロリポップのデータベースを調べてみました。

ライトプランの特徴は以下の通りです:

  • 月額料金: 220円〜
  • ディスク容量: 350GB
  • MySQLデータベース: 最大50個

私の場合は既にWordpressがデータベースを1個つかっているはずなので、あと49個のデータベースを作れます。データベース数は十分ですね。

というわけで、ロリポップでWebアプリケーションを作るには、

  • Python言語を学ぶ
  • Python言語用のWebアプリケーションフレームワークFlaskを学ぶ
  • MySQLデータベースを学ぶ

これでなんとかなりそうです。

    1. (なんにも考えず)ロリポップのライトプランでサーバー借りてみた。そして何ができるか調べてみる。
    2. ロリポップでデータベースを調べる
  1. PCにPythonの開発環境を構築
    1. 主な特徴
    2. ライセンス
    3. Minicondaのインストール
    4. Minicondaのインストール手順 (Intel Mac用)
    5. 特定のPythonバージョンの仮想環境を作成
  2. flaskのインストール
  3. 開発環境のインストール
    1. 機能拡張(プラグイン)導入
  4. ワークスペースの作成
  5. GitHub Copilotを使う
  6. Hello Flask!
  7. ロリポップのライトプランにはSSHは使えません
    1. Cyberduckのインストール
    2. SSHを使わないでどうやってFlaskインストールするか
  8. Flaskの直接使用
    1. 直接使用する場合の注意点
    2. 1. Flaskのソースコードをダウンロード:
    3. 2. ソースコードをプロジェクトに含める:
    4. 3. Flaskの依存関係を解決:
    5. 4. コードでFlaskをインポート:
  9. プロジェクトの構成
    1. index.cgiを用意する
    2. app.pyでFlaskを使ったコーディング
    3. .htaccess
    4. 1. CGIスクリプトを実行することを許可
    5. 2. .cgi 拡張子を持つファイルをCGIスクリプトとして処理
    6. 3. URLリライトエンジンを有効に
    7. 4. クエストされたファイルが実際のファイルでない場合にリライトルールを適用
    8. 5. 特定のパターンにマッチするURLを別のURLにリライト
  10. FTPによるファイルの配置
  11. 動作確認
  12. デコレータ
    1. デコレータの基本
    2. デコレータの詳細な仕組み
    3. デコレータの実用例
    4. 複数のデコレータを使う
    5. 結論
  13. ルーティング
    1. 基本的なルーティング
    2. ルートのパラメータ
    3. パラメータの型指定
    4. コンバータの使用方法
      1. ビルトインコンバータ
  14. Jinjaテンプレートを使用する
    1. render_templateを使ってテンプレートを表示する
    2. Jinjaテンプレートについて
    3. テンプレートは templates フォルダに入れる
  15. テンプレートの継承
    1. 親テンプレートの作成
  16. <!-- templates/top.html --> {% extends "base.html" %} {% block title %}TOP{% endblock %} {% block content %} <h2>Welcome to the TOP page</h2> <p>This is the top page of my website.</p> {% endblock %} この top.html は、base.html を継承し、{% block title %} と {% block content %} を上書きしています。 同様に、他のページも同様に作成できます。
  17. <!-- templates/detail.html --> {% extends "base.html" %} {% block title %}Item Detail{% endblock %} {% block content %} <h2>Item Detail</h2> <p>Here is the detail of the item.</p> {% endblock %} ルートでの使用
  18. url_forの使い方
    1. 基本的な使い方
      1. 例:基本的な使用
      2. 例:パラメータ付きURL
    2. URLクエリパラメータの追加
      1. 例:クエリパラメータの追加
  19. テンプレートで制御文を使う
    1. if文の使用
      1. 例:if文の使用
    2. for文の使用
      1. 例:for文の使用
    3. if文とfor文の組み合わせ
      1. 例:if文とfor文の組み合わせ
  20. Jinjaのフィルター機能
    1. ビルトインフィルターの例
      1. upper
      2. lower
      3. title
      4. length
      5. default
    2. カスタムフィルターの定義
      1. カスタムフィルターの定義
      2. カスタムフィルターの使用
    3. 文全体に対してフィルターを適用する方法
    4. filter ブロックの使用
      1. 例1: テキストを大文字に変換する
      2. 例2: テキストをタイトルケースに変換する
    5. フィルター一覧
  21. エラーハンドリング
    1. 404エラーハンドリングの設定
      1. 例: 404エラーハンドラーの実装
      2. 404エラーページのテンプレート
    2. abort関数の使用方法
    3. エラーハンドラーとabortの組み合わせ
    4. カスタムエラーページのテンプレート
  22. Formを使用したプログラム作成
    1. app.py の内容
  23. from flask import Flask, request # ==================================== # Create a new Flask instance # ==================================== app = Flask(__name__) # ==================================== # Define a route # ==================================== # Obtain Data from GET Request @app.route('/get') def do_get(): name = request.args.get('name', 'no name') return f'Hello, {name}!' # Obtain Data from POST Request @app.route('/', methods=['GET', 'POST']) def do_post(): if request.method == 'POST': name = request.form['name'] return f'Hello, {name}!' else: return ''' <h2>Send by POST method</h2> <form method="post"> name: <input type="text" name="name"> <input type="submit" value="送信"> </form> ''' # ==================================== # Run the app # ==================================== if __name__ == '__main__': app.run(debug=True) コードの解説
    1. do_post関数
    2. GETリクエストの挙動
    3. POSTリクエストの挙動
    4. do_post関数のまとめ
    5. 全体の流れ
  24. WTFormsとは
    1. WTFormsのバージョン
    2. WTFormsの使用方法
    3. バリデーション
    4. novalidate属性
    5. テンプレートマクロ
    6. カスタムバリデータ
    7. フォームの使用例
    8. テンプレートの例
  25. Flask-WTFを使う
    1. Flask-WTFのインストール
    2. Flask-WTFの使用方法
      1. フォームクラスの定義
      2. Flaskアプリケーションの設定
    3. テンプレートの定義
      1. フォームクラスの定義
      2. Flaskアプリケーションの設定
      3. テンプレートの定義
    4. 追加の機能
      1. カスタムバリデータ
  26. Flask-WTFとPRGパターン
    1. 概要
    2. サンプルコード
      1. 1. アプリケーション設定 (app.py)
      2. 2. フォーム定義 (forms.py)
      3. 3. テンプレート (input.html)
      4. 6. フォームヘルパー (_formhelpers.html)
    3. 詳細解説
      1. PRGパターン (Post/Redirect/Get パターン)
      2. CSRF保護
      3. バリデーション
      4. テンプレートマクロ
  27. 1. 必要なライブラリのインストール
    1. Flask関連のライブラリ
    2. インストール済みのライブラリの確認
    3. MySQLクライアントのインストール
  28. 2. MySQLサーバーの設定
  29. 3. Flaskプロジェクトのセットアップ
    1. ディレクトリ構成
  30. 4. config.py ファイルの設定
  31. 5. モデルの作成
    1. SQLAlchemyについて
  32. 6. Flaskアプリの設定
  33. 7. テンプレートの作成
  34. 8. アプリケーションの実行
    1. Flask-Migrateの基本的な使い方
    2. 使用したコマンドの解説
  35. Blueprint
  36. Flaskのg
    1. 使用例
      1. 1. データベース接続の設定
      2. 2. ルートでの使用
  37. Flaskのデバッグモード
    1. 1. デバッグモードの有効化方法
    2. 2. デバッグモードでできること
    3. 3. Debugger PINについて
    4. 4. 修正のリロード
  38. メモ帳アプリの作成
    1. DBの準備
    2. 解説
  39. flashについて
    1. 解説
    2. 解説
    3. 解説
    4. 解説
    5. 解説
    6. 解説
    7. 秘密鍵について
    8. 解説
    9. 解説
    10. 解説
  40. Flask-Login
    1. 主な機能
      1. FlashLoginのインストール
      2. アプリケーションの設定
      3. ユーザーモデルの定義
      4. ユーザーのロード関数の定義
      5. ログインとログアウトの実装
    2. 説明
  41. Bootstrap

PCにPythonの開発環境を構築

手持ちのマックにMinicondaのインストールを行います。

Minicondaは、Anaconda Distributionの最小限のバージョンで、Pythonやその他のプログラムに依存関係を管理するためのパッケージ管理システムであるCondaを提供します。Minicondaは、最小限のインストールでありながら、必要に応じてパッケージを追加してカスタマイズできるため、軽量で柔軟な環境を構築するのに適しています。

主な特徴

  1. 軽量インストール:
    • Minicondaは最小限のインストールであり、必要なパッケージのみをインストールできます。
  2. パッケージ管理:
    • Condaを使用してパッケージのインストール、アップデート、削除を簡単に行うことができます。
  3. 仮想環境管理:
    • Condaを使用して複数の仮想環境を作成し、異なるプロジェクトで異なるパッケージやPythonバージョンを使用することができます。

ライセンス

Minicondaは、BSD 3-Clause “New” or “Revised” License(BSD-3-Clause)でライセンスされています。これは、広く使われているオープンソースライセンスで、ソフトウェアの再配布と使用に関する緩やかな制約を提供します。

Minicondaのインストール

Miniconda - Anaconda

私が使っているM1 Macの場合、Minicondaをインストールするには、ARM64アーキテクチャに対応したバージョンを選択する必要があります。

というわけでM1 Macでの構築は諦め最近使ってなかったIntel Mac Miniを引っ張り出してきて使用することに。まさか今さらIntel Macを使うことになるとは思ってもいなかったです。

Minicondaのインストール手順 (Intel Mac用)

  1. Minicondaのダウンロード:
    • Minicondaの公式ダウンロードページにアクセスし、Miniconda3 macOS Intel x86 64-bit bash用のインストーラーをダウンロードします。
    • Miniconda公式ダウンロードページ
    • curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh > Miniconda3-latest-MacOSX-x86_64.sh
  2. インストーラーの実行:
    • ダウンロードしたインストーラーをターミナルで実行します。以下のコマンドを使用します。
      • bash Miniconda3-latest-MacOSX-x86_64.sh
  3. インストールプロセスに従う:
    • インストール中に表示されるプロンプトに従って、インストールディレクトリを指定し、インストールを完了します。
    • デフォルトの設定を選択する場合は、基本的に「Enter」キーを押して進むことができます。
    • ENTERで続行。ライセンスはスペースでページ送りできます。
    • ライセンスに同意します。
    • インストール先を選択します。特に問題なければENTERで進みます。
    • インストールが完了しました
  4. 環境変数の設定:
    • インストールが完了したら、ターミナルを再起動するか、次のコマンドを実行して環境変数を更新します。
      • source ~/.bash_profile
    • または、zshを使用している場合は次のコマンドを実行します。Catalina世代以降のデフォルトシェルはzshです。
      • source ~/.zshrc
    • Condaの動作確認:
      • Condaが正しくインストールされているかを確認するために、次のコマンドを実行します。
      • conda --version
      • 正常にインストールされていれば、Condaのバージョンが表示されます。

特定のPythonバージョンの仮想環境を作成

インストールが完了したら、特定のPythonバージョンを使用する仮想環境を作成します。今回はロリポップサーバーのバージョンに合わせます。

conda create --name flask_env python=3.7
## 確認
conda env list

次に、その環境をアクティベートします。

(base) % conda activate flask_env

アクティベートすると、仮想環境名がbaseからflask_envにかわり、今どの仮想環境が有効になっているのかわかります。

(flask_env) % 

抜ける時は deactivateです

(flask_env) % conda deactivate
(base) %

flaskのインストール

pip installで、仮想環境へインストールします。

さて、ここで問題になるのがFlaskのバージョンです。ロリポップでは古いPython3.7しか対応していないので、FlaskのバージョンもPython3.7をサポートしている最終バージョンを選択します。flaskのサイトによると、Version 2.3.0Python 3.7のサポートを終了しています。そこで、flask 2.2.5を使用しましょう。

(base) % conda activate flask_env
(flask_env) % pip install flask==2.2.5

開発環境のインストール

Gitのインストールを行います。Macの場合は次のコマンドでインストールできます。

xcode-select --install

VSCodeをインストールします。

Visual Studio Code - The open source AI code editor
Visual Studio Code redefines AI-powered coding with GitHub Copilot for building and debugging modern web and cloud appli...

上記サイトからダウンロードしたMac用ファイルを「アプリケーション」フォルダに移動すればインストール完了です。

機能拡張(プラグイン)導入

まずはPythonの機能拡張を入れます。

次に、Better Jinja機能拡張を入れます。

(任意)GitHub CopilotとCopilot Chatも入れておきます。

(任意)Flake8はソースコードの問題をチェックするツールです。

言語パックです。日本語化できます。

これをインストールすると、「Change Language and Restart」というメッセージが表示されます。クリックするとVSCodeが再起動し、日本語化されます。

ワークスペースの作成

% cd
% mkdir work_flask
% cd work_flask

メニューの「ファイル」>「フォルダを開く」を選択、work_flaskを開く。

「はい、作成者を信頼します」をクリック。

メニューの「ターミナル」>「新しいターミナル」を開いて、仮想環境を有効にします。

(base) h% conda activate flask_env
(flask_env)  % 

GitHub Copilotを使う

AIで時短しましょう。タイパ最強の生成AIを使わない手はありません。

たまに間違うけど、大体合ってるし、わからない事は聞けばすぐ答える、間違いを指摘すればすぐ直してくれる、そんな、強力なペアプログラマーを得た感覚です。

Hello Flask!

hello-sampleフォルダを作成。その中にapp.pyファイルを作成。

from flask import Flask

# ====================================
# Create a new Flask instance
# ====================================
app = Flask(__name__)

# ====================================
# Define a route
# ====================================
@app.route('/')
def hello():
    return 'Hello, World!'

下部にPythonのバージョンが書かれている場所があります。今、3.8.2となっているので、ここをクリックします。すると、Select Interpriterが開くので、今回のターゲットバージョンであるPython 3.7("flask_env")を選択します。

では実行しましょう。

(flask_env) work_flask % cd hello-sample 
(flask_env) hello-sample % flask --app app run
 * Serving Flask app 'app'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [30/Jul/2024 20:21:03] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [30/Jul/2024 20:21:03] "GET /favicon.ico HTTP/1.1" 404 -

実行すると Runnning on http://127.0.0.1:5000 と表示されるので、Commandキーを押しながら、URLをクリックしてブラウザで表示します。

ターミナルでCtrl+Cを押すと Flaskを止めることができます。

では次にこれをLolipopサーバーで動かしてみましょう。

ロリポップのライトプランにはSSHは使えません

なんということでしょう。ロリポップのライトプランでは、SSHは使えないのだそうです。

SSHは、スタンダードプラン、ハイスピードプラン、エンタープライズプランで利用できます。と書いてあります。うーんそうかライトプランは無理か。

というわけで、SSHを使わないで頑張ってFlaskを動かしてみましょう。FTPでデプロイするだけで動く方向で検討します。

Cyberduckのインストール

MacにおけるFTPクライアントには以下のソフトを使いますのでインストールしておいてください。

Cyberduck | Libre server and cloud storage browser for Mac and Windows with support for FTP, SFTP, WebDAV, Amazon S3, OpenStack Swift, Backblaze B2, Microsoft Azure & OneDrive, Google Drive and Dropbox

SSHを使わないでどうやってFlaskインストールするか

本来であれば、Flaskを使用するためには、基本的にFlaskパッケージをインストールする必要があります。Pythonのパッケージは、一般的にインストールされることで、コードから簡単にインポートして使用できるようになります。Flaskも例外ではありません。そのためにはSSHでログインします。しかし、前述の通りロリポップのライトプランにはSSH接続は提供されていません。

Flaskをプロジェクトに含めちゃう作戦でいきましょう。つまり、インストールできないのであれば、ソースコードをまるっと含めればいいのです。言うなれば手動インストールですね。例えば、FlaskのソースコードはGithubで公開されています。依存するソフトウェアも同様です。

Release 2.2.5 · pallets/flask
This is a security fix release for the 2.2.x release branch. Note that 2.3.x is the currently supported release branch; ...
Tags ?? pallets/click
Python composable command line interface toolkit. Contribute to pallets/click development by creating an account on GitH...
Tags ?? pallets/werkzeug
The comprehensive WSGI web application library. Contribute to pallets/werkzeug development by creating an account on Git...

Flaskの直接使用

Flaskをインストールせずに使いたい場合、Flaskのソースコードを直接プロジェクトに含める方法があります、まあでもこれは推奨される方法ではありません。

直接使用する場合の注意点

Flaskのソースコードを直接使用する場合、以下の手順に従いますが、複雑で手間がかかるため、あまり推奨されません。でもライトプランでは仕方がありません。頑張って作業して進めることにしました。

1. Flaskのソースコードをダウンロード:

Flaskのソースコードは、FlaskのGitHubリポジトリからダウンロードできます。

2. ソースコードをプロジェクトに含める:

ダウンロードしたソースコードをプロジェクトディレクトリにコピーします。

3. Flaskの依存関係を解決:

FlaskにはWerkzeugやJinjaなどの依存関係があります。これらも同様にソースコードをダウンロードしてプロジェクトに含める必要があります。

例えば
clickならhttps://github.com/pallets/click/releases/tag/8.1.7
werkzeugならhttps://github.com/pallets/werkzeug/tags?after=2.3.3
などからバージョンを指定してダウンロードすることができます。

Flaskの依存関係はFlaskのソースコードを開き、setup.pyを見ることで確認できます。さらにその依存関係先の依存関係をさらにチェック・・・するのは面倒なのでvenvで環境を作って、Flaskをpipでインストールしておき、pip freeze > requirements.txtを実行してrequirements.txtを作成しておきます。次のようなコマンドになると思います。

cd hello-sample
python3 -m venv menv
source menv/bin/activate
pip install flask
pip freeze > requirements.txt

こうし出来たrequirements.txtの中身は次のようになります。flask==2.2.5の場合のです。

click==8.1.7
Flask==2.2.5
importlib-metadata==6.7.0
itsdangerous==2.1.2
Jinja2==3.1.4
MarkupSafe==2.1.5
typing_extensions==4.7.1
Werkzeug==2.2.3
zipp==3.15.0

これらの依存パッケージをバージョン指定でGithubからダウンロードします。ソースコードはZIPファイルになっているので、展開してフォルダごとdependenciesフォルダに入れておきます。

4. コードでFlaskをインポート:

プロジェクト内でFlaskのパスを設定し、Flaskをインポートします。後述するindex.cgi内で実装例を示します。

プロジェクトの構成

プロジェクトにはdependenciesというフォルダを用意し、Githubからダウンロードしたソースコードをプロジェクトに追加しています。

../hello-sample
├── app.py
├── dependencies
│   ├── click-8.1.7
│   ├── flask-2.2.5
│   ├── importlib_metadata-6.7.0
│   ├── itsdangerous-2.1.2
│   ├── jinja-3.1.4
│   ├── markupsafe-2.1.5
│   ├── typing_extensions-4.7.1
│   ├── werkzeug-2.2.3
│   └── zipp-3.15.0
├── index.cgi
└── requirements.txt

index.cgiを用意する

index.cgi ファイルは、CGI(Common Gateway Interface)を使用してWebサーバー上でPythonスクリプトを実行するためのエントリーポイントです。

#!/usr/local/bin/python3.7
import cgitb
cgitb.enable()
import sys
import os

sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/flask-2.2.5/src'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/werkzeug-2.2.3/src'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/jinja-3.1.4/src'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/click-8.1.7/src'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/importlib_metadata-6.7.0/'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/markupsafe-2.1.5/src'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/itsdangerous-2.1.2/src'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/typing_extensions-4.7.1/src'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/zipp-3.15.0/'))

from wsgiref.handlers import CGIHandler
from app import app
CGIHandler().run(app)

CGIデバッグの有効化:

import cgitb
cgitb.enable() # Enable CGI traceback for debugging

cgitb モジュールを使用して、スクリプト内のエラーをHTML形式で表示します。デバッグに役立ちます。

import sys
import os
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/flask-2.2.5/src'))
sys.path.insert(0, os.path.join(os.getcwd(), 'dependencies/werkzeug-2.2.3/src'))
…

sys.path.insert(0, path) を使用して、依存関係のディレクトリをPythonのモジュール検索パスに追加します。これにより、これらのパッケージがインポート可能になります。

app.pyでFlaskを使ったコーディング

通常のFlaskのコーディングを行います

from flask import Flask

# ====================================
# Create a new Flask instance
# ====================================
app = Flask(__name__)

# ====================================
# Define a route
# ====================================
@app.route('/')
def hello():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(debug=True)

.htaccess

最後に、cgiを実行できるように .htaccessを設置します。

Options +ExecCGI
AddHandler cgi-script .cgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /hello-sample/index.cgi/$1 [QSA,L]

このApache HTTPサーバーの設定は、CGIスクリプトを実行し、特定のURLパターンをリライトするためのものです。各ディレクティブの詳細な解説を以下に示します。

1. CGIスクリプトを実行することを許可

Options +ExecCGI
  • 説明: このディレクティブは、ディレクトリ内でCGIスクリプトを実行することを許可します。
  • 詳細: Apacheサーバーでは、Options ディレクティブを使用してディレクトリのさまざまな動作を設定できます。ExecCGI オプションを有効にすることで、そのディレクトリ内の .cgi スクリプトを実行可能にします。

2. .cgi 拡張子を持つファイルをCGIスクリプトとして処理

AddHandler cgi-script .cgi
  • 説明: このディレクティブは、.cgi 拡張子を持つファイルをCGIスクリプトとして処理するように設定します。
  • 詳細: AddHandler ディレクティブを使用して、特定の拡張子のファイルを特定のハンドラーで処理するようにApacheに指示します。ここでは、.cgi ファイルを cgi-script ハンドラーで処理するように設定しています。

3. URLリライトエンジンを有効に

RewriteEngine On
  • 説明: このディレクティブは、URLリライトエンジンを有効にします。
  • 詳細: Apacheのモジュール mod_rewrite を使用すると、URLのリクエストをリライト(変更)することができます。RewriteEngine On は、リライトエンジンを有効にするためのコマンドです。

4. クエストされたファイルが実際のファイルでない場合にリライトルールを適用

RewriteCond %{REQUEST_FILENAME} !-f
  • 説明: このディレクティブは、リクエストされたファイルが実際のファイルでない場合にリライトルールを適用する条件を指定します。
  • 詳細: RewriteCond ディレクティブは、次の RewriteRule を適用する条件を定義します。ここでは、リクエストされたパスが実際のファイル(存在するファイル)でない場合にのみ、次のリライトルールを適用するという条件を設定しています。

5. 特定のパターンにマッチするURLを別のURLにリライト

RewriteRule ^(.*)$ /hello-sample/index.cgi/$1 [QSA,L]
  • 説明: このディレクティブは、特定のパターンにマッチするURLを別のURLにリライトします。
  • 詳細: RewriteRule は、URLのリクエストを別の形式に変換するためのルールを定義します。
    • ^(.*)$: リクエストされたURLのパス全体にマッチする正規表現パターン。(.*) は任意の文字列にマッチします。
    • /hello-sample/index.cgi/$1: リクエストを /hello-sample/index.cgi/ にリライトし、元のリクエストのパス部分($1)を引数として渡します。
    • [QSA,L]: リライトルールのフラグ。
      • QSA (Query String Append): 既存のクエリ文字列を保持し、新しいクエリ文字列を追加します。
      • L (Last): これが最後のリライトルールであることを示し、それ以降のルールを無視します。

FTPによるファイルの配置

ここまで完成したらCyberduckなどのFTPソフトを使って、hello-sampleフォルダごとサーバーにアップロードしましょう。

ファイルを配置したら最後にパーミッションを設定します。

.htaccessファイル604(rw—-r–)
app.py700(rwx——)
index.cgi700(rwx——)
dependenciesフォルダ705(rwx—r-x)
パーミッションを上の通り設定します。これが意外と重要で、適当なパーミッションだとセキュリティ上の理由からCGIが実行されないことがあるらしいので、ちゃんと設定します。Cyberduckの場合、ファイルを右クリックし、情報を選択するか、[Command + I]キーを押して情報ダイアログを開いてパーミッションを変更できます。

動作確認

では確認です。ブラウザーを開き、 https://あなたのドメイン/hello-sample/にアクセスすると、Hello Worldが表示されます。

お疲れ様でした、これでFlaskによるHello Worldがロリポップのライトプランでも実行できました。

デコレータ

Pythonのデコレータは、関数やメソッドの動作を変更するための非常に強力なツールです。デコレータはPython 2.4以降のバージョンで使用可能です。以下では、デコレータの基本的な使い方とその仕組みについて詳しく解説します。

デコレータの基本

デコレータは他の関数を引数として取り、その関数に何らかの追加処理を施して、新しい関数を返す関数のことです。基本的なデコレータの構文は以下のようになります。

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Something is happening before the function is called.")
        result = func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

この例では、say_hello 関数に my_decorator を適用しています。@my_decorator の部分がデコレータを適用するシンタックスシュガーです。say_hello が呼ばれると、実際には wrapper 関数が実行され、前後にメッセージが表示されます。

デコレータの詳細な仕組み

  1. デコレータ関数: デコレータは関数を引数として取り、新しい関数を返します。
  2. ラッパー関数: デコレータ内部で定義されるラッパー関数(wrapper 関数)は、元の関数を実行する前後に追加の処理を挿入します。
  3. 引数の受け渡し: ラッパー関数は元の関数と同じ引数を受け取るようにします(*args**kwargs を使う)。

デコレータの実用例

以下は、関数の実行時間を計測するデコレータの例です。

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} took {end_time - start_time} seconds to execute.")
        return result
    return wrapper

@timer
def long_running_function():
    time.sleep(2)
    print("Finished long running function.")

long_running_function()

この例では、long_running_function が実行されると、その実行時間が計測されて表示されます。

複数のデコレータを使う

複数のデコレータを適用することも可能です。この場合、デコレータは内側から外側へ順に適用されます。

def decorator1(func):
    def wrapper(*args, **kwargs):
        print("Decorator 1")
        return func(*args, **kwargs)
    return wrapper

def decorator2(func):
    def wrapper(*args, **kwargs):
        print("Decorator 2")
        return func(*args, **kwargs)
    return wrapper

@decorator1
@decorator2
def greet():
    print("Hello, World!")

greet()

この場合、greet 関数は decorator2 によって最初にラップされ、その後 decorator1 によってラップされます。結果として、以下の出力が得られます。

Decorator 1
Decorator 2
Hello, World!

結論

Pythonのデコレータは非常に柔軟で強力な機能です。関数やメソッドの前後に追加の処理を挿入するために利用され、コードの再利用性や可読性を向上させるのに役立ちます。以降、Flaskでどのようにデコレータを使うのか見ていきましょう。

ルーティング

Flaskでは、ルーティング機能を使用してURLと関数(ビュー関数)を紐付けます。ルーティングは、特定のURLにアクセスした際にどの関数を実行するかを決定する重要な機能です。以下に、Flaskにおけるルーティングの基本的な使い方を説明します。

基本的なルーティング

以下は、基本的なFlaskアプリケーションの例です。この例では、3つのルートを定義しています。1つはトップページ(/)、もう1つは商品ページ(/list)、3つ目は詳細ページ(/detail)です。

from flask import Flask

# ====================================
# Create a new Flask instance
# ====================================
app = Flask(__name__)

# ====================================
# Define a route
# ====================================
@app.route('/')
def hello():
    return '<H1>Top page</H1>'

@app.route('/list')
def item_list():
    return '<H1>Item list</H1>'

@app.route('/detail')
def item_detail():
    return '<H1>Item detail</H1>'

if __name__ == '__main__':
    app.run(debug=True)

ルートのパラメータ

ルーティングでは、URLパラメータを使って動的なURLを作成することもできます。以下の例では、<name>というパラメータを持つルートを定義しています。

@app.route('/hello/<name>')
def hello_name(name):
    return f'Hello, {name}!'

この場合、/hello/John のようにアクセスすると、Hello, John! と表示されます。

パラメータの型指定

Flaskでは、URLパラメータの型を指定することもできます。デフォルトでは、すべてのパラメータは文字列として扱われますが、整数や浮動小数点数などの型を指定することも可能です。

@app.route('/user/<int:user_id>')
def show_user(user_id):
    return f'User ID is {user_id}'

この例では、<int:user_id> と指定することで、user_id パラメータが整数として扱われます。

もし,user_idパラメータが数値ではない場合、Flaskは404エラーとなり、「Not Found」エラーとなります。

<int:user_id>intのことをコンバータと呼びます。Flaskにおけるコンバータ(Converters)は、ルートで指定するURLパラメータの型を変換するための仕組みです。デフォルトでは、FlaskはURLパラメータをすべて文字列として扱いますが、コンバータを使用することで、整数や浮動小数点数などの特定の型に変換することができます。

コンバータの使用方法

Flaskにはいくつかのビルトインコンバータが用意されています。以下に、一般的に使用されるコンバータの一覧とその使用例を示します。

ビルトインコンバータ

  • string:デフォルトのコンバータ。任意の文字列にマッチします。
  • int:整数にマッチします。
  • float:浮動小数点数にマッチします。
  • path:スラッシュを含む文字列にマッチします。
  • uuid:UUID形式の文字列にマッチします。

了解しました。それでは、すべてのソースコードを一つにまとめて表示し、さらにJinjaテンプレートについても解説します。

Jinjaテンプレートを使用する

from flask import Flask, render_template

# ====================================
# Create a new Flask instance
# ====================================
app = Flask(__name__)

# ====================================
# Define a route
# ====================================

# Top page
@app.route('/')
def index():
    return render_template('top.html')

# Item list
@app.route('/list')
def item_list():
    return render_template('list.html')

# Item detail
@app.route('/detail')
def item_detail():
    return render_template('detail.html')

# ====================================
# Run the app
# ====================================
if __name__ == '__main__':
    app.run(debug=True)

render_templateを使ってテンプレートを表示する

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

Jinjaテンプレートについて

FlaskはJinjaというテンプレートエンジンを使用します。Jinjaテンプレートを使用すると、HTML内にPythonコードを埋め込むことができ、動的にコンテンツを生成することができます。

以下に、top.html の例を示します:

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>TOP</title>
    </head>
    <body>
        <h1>top</h1>
        <hr />
    </body>
</html>

このテンプレートはシンプルなHTMLですが、Jinjaテンプレートエンジンを使用することで、動的なデータを埋め込むことができます。例えば、以下のように変数を使うことができます:

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>{{ title }}</title>
    </head>
    <body>
        <h1>{{ heading }}</h1>
        <hr />
    </body>
</html>

このテンプレートでは、titleheading という変数が使われています。これらの変数は render_template 関数を使用して渡すことができます。

@app.route('/')
def index():
    return render_template('top.html', title="TOP", heading="Welcome to the TOP page")

テンプレートは templates フォルダに入れる

Flaskはデフォルトでテンプレートファイルを templates フォルダ内から探します。このフォルダ構成により、プロジェクトのディレクトリが整理され、Flaskがテンプレートを簡単に見つけることができます。

ディレクトリ構造の例:

my_flask_app/
├── app.py
└── templates/
    ├── top.html
    ├── list.html
    └── detail.html

この構造により、Flaskは templates フォルダ内のテンプレートファイルを自動的に認識し、適切にレンダリングすることができます。

テンプレートの継承

テンプレートの継承は、FlaskとJinjaテンプレートエンジンの強力な機能の一つで、共通のレイアウトを持つ複数のページを効率的に作成するために使用されます。テンプレートの継承を使用することで、ページごとに異なる部分だけを定義し、共通部分を親テンプレートにまとめることができます。これにより、コードの重複を避け、保守性を向上させることができます。

以下では、テンプレートの継承の基本的な使い方を説明します。

親テンプレートの作成

まず、共通のレイアウトを持つ親テンプレートを作成します。例えば、base.html というファイルを templates フォルダに作成します。

<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <header>
        <h1>My Website</h1>
        <nav>
            <ul>
                <li><a href="/">Home</a></li>
                <li><a href="/list">List</a></li>
                <li><a href="/detail">Detail</a></li>
            </ul>
        </nav>
    </header>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer>
        <p>© 2024 My Website</p>
    </footer>
</body>
</html>

この base.html は親テンプレートで、{% block title %}{% block content %} という2つのブロックを定義しています。これらのブロックは、子テンプレートで上書きされる部分です。

子テンプレートの作成

次に、base.html を継承する子テンプレートを作成します。例えば、top.html を以下のように作成します。

コメント

タイトルとURLをコピーしました