HOWTO · Python
HTML で Python を実行する
HTML で Python を実行する方法を学ぶ
このページの内容
静的なHTMLにスクリプトを置いただけでは、ブラウザーでサーバー側のPythonが実行されるわけではありません。Pythonで生成した内容を表示するには、サーバー上でPythonを実行し、その出力をHTTPレスポンスとして返します。小規模な連携ならPHPアプリケーションからPythonプロセスを起動できます。Djangoアプリケーションでは通常、ビューからテンプレートへデータを渡します。
PHPを使ってHTML内でPythonスクリプトを実行する
ページを.phpなどPHPで処理される拡張子で保存し、PHPが設定されたサーバーから配信します。サーバーにはPythonインタープリターも必要で、PHPから起動できる権限が必要です。次の例は、短いPythonスクリプトを作成し、2つの引数を安全に渡して、取得した結果をレスポンスに含める一連の処理を示します。
<?php
$pythonScript = <<<'PY'
import sys
name = sys.argv[1]
count = int(sys.argv[2])
print(f"Hello, {name}! Count: {count}")
PY;
$scriptPath = tempnam(sys_get_temp_dir(), 'page-python-');
file_put_contents($scriptPath, $pythonScript);
$command = 'python3 ' . escapeshellarg($scriptPath)
. ' ' . escapeshellarg('Mina')
. ' ' . escapeshellarg('3');
$result = shell_exec($command);
unlink($scriptPath);
?><!doctype html>
<html lang="en">
<body>
<p><?= htmlspecialchars($result ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></p>
</body>
</html>
ここではPHPがpython3を起動し、PythonプロセスはMinaと3をそれぞれsys.argv[1]とsys.argv[2]として受け取ります。shell_exec()がプロセスの出力を取得し、htmlspecialchars()がページに挿入する前にHTML用にエンコードします。この出力はブラウザーに送られるレスポンスの内容であり、サーバーのコンソールに表示されるテキストではありません。
shell_exec()が使えるかどうかはPHPホストの設定によります。また、Webサーバーの実行アカウントにインタープリターを起動する権限が必要です。この例では固定の引数を使っています。動的な値を渡す場合は検証し、各引数を個別にescapeshellarg()でエスケープしてください。信頼できない入力をシェルコマンドに連結してはいけません。規模の大きいアプリケーションでは、リクエストごとにプロセスを起動するより、ジョブキューや専用サービスのほうが適している場合があります。
Djangoを使ってHTML内でPythonスクリプトを実行する
Djangoアプリケーションでは、アプリケーションの処理をPythonのビューに記述し、その結果をテンプレートに渡します。テンプレートはサーバー上で値をHTMLに描画します。ブラウザーが受け取るのは描画済みのページであり、Pythonを実行することはありません。たとえば、ビューでcontext = {"message": "Hello from Django"}を用意してrender(request, "page.html", context)を返し、テンプレートでは{{ message }}を使って値を表示できます。
テンプレート内で再利用可能な表示処理を行うには、カスタムテンプレートタグが便利です。coreという名前のインストール済みアプリで、core/templatetags/__init__.pyとcore/templatetags/my_custom_tags.pyを作成します。後者ではdjangoからtemplateをインポートし、register = template.Library()を設定して、たとえばdef greeting(): return "Hello from Django"のような関数を@register.simple_tagでデコレートします。Djangoがtemplatetagsパッケージを認識できるよう、追加後は開発サーバーを再起動してください。
テンプレートで{% load my_custom_tags %}を使ってモジュールを読み込み、{% greeting %}でタグを呼び出します。このタグはサーバー側のテンプレート描画用にテキストを返すもので、ブラウザーのHTML内で任意のPythonを実行するものではありません。単純な値なら、カスタムタグよりビューとテンプレートコンテキストを使うほうが通常は分かりやすくなります。Djangoにはdate、linebreaks、safe、randomなどの組み込みフィルターもあります。詳しくはDjangoの組み込みテンプレートフィルターのリファレンスを参照してください。
ページの読み込み後にデータが必要な場合は、Djangoのビューをエンドポイントとして公開し、fetch()や別のAJAXクライアントからリクエストできます。機密データを返したり操作を実行したりする前に、認証と認可を確認してください。状態を変更するPOSTリクエストでは、DjangoのCSRF保護を利用し、CSRFトークンを送信します。エンドポイントをPOSTのみに制限しても、それだけで安全になるわけではありません。詳しくはDjangoのCSRFドキュメントを参照してください。
PHPでホストされているサイトに小規模な既存Pythonスクリプトを組み込み、ホストが実行を許可している場合は、PHPからプロセスを起動する方法が適しています。Djangoアプリケーションでページのデータを計算して描画するには、通常ビューとテンプレートを使います。テンプレート内で表示処理を再利用する場合はカスタムタグを、ページ読み込み後に取得するデータにはエンドポイントを使います。