htmx-patterns について
HTMXで動的な画面を作るDjango開発者向けのパターンガイドです。サーバー描画の部分テンプレート、リクエスト処理、フォームのフィードバックやエラー対応を扱います。
主な機能
- 01HTMXリクエストの検出
- 02部分テンプレートの構成
- 03フォーム検証とフィードバック
- 04レスポンスヘッダーによる動作
- 05ローディングとエラー処理
活用シーン
- 01HTMXリクエストへのHTMLフラグメント返却
- 02段階的に機能を強化するDjangoページの構築
- 03フォーム送信と検証エラーの処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ waldencui/ claude-code-django --skill htmx-patternsインストール後、Claude Code で/htmx-patternsを入力して読み込まれたか確認します。
詳細
Django 向け HTMX パターン
中核となる考え方
- サーバーは JSON ではなく HTML をレンダリングします。HTMX リクエストにはデータではなく HTML フラグメントを返します
- 動的な更新には部分テンプレートを使います。HTMX のレスポンス用に個別の
_partial.htmlファイルを用意します - プログレッシブエンハンスメントを採用します。JavaScript がなくてもページは動作し、HTMX によって UX が向上します
- クライアント側の複雑さを最小限に抑え、面倒な処理はサーバーに任せます
重要なヒントと注意事項
UX のベストプラクティス
必ずローディングインジケーターを表示してください
- リクエスト中の読み込み状態を表示するには
hx-indicatorを使います - ユーザーが操作の結果を不安に思うことがないようにします
- 例:
<button hx-get="/data/" hx-indicator="#spinner">Load</button>
必ずユーザーにフィードバックを提供してください
- 成功やエラーのフィードバックには Django のメッセージフレームワークを使います
- エラーメッセージは黙って失敗させるのではなく、HTMX のレスポンスに含めて返します
- 操作が完了した後に何が起きたのかを表示します
エラーを適切に処理してください
- 適切な HTTP ステータスコードを返します(バリデーションエラーには 400、サーバーエラーには 500)
- 部分テンプレートにフォームエラーをレンダリングします
- 例外を握りつぶさず、ログに記録してユーザーにわかりやすいメッセージを表示します
Django 固有のパターン
必ず HTMX リクエストを検出してください
request.headers.get("HX-Request")を確認して、HTMX リクエストを検出します- HTMX の場合は部分テンプレートを返し、それ以外の場合はページ全体のテンプレートを返します
- パターン:
if request.headers.get("HX-Request"): return render(request, "_partial.html", context)
HTMX リクエストには必ず部分テンプレートを返してください
- HTMX リクエストには
base.htmlを含むページ全体ではなく、_partial.htmlテンプレートを返します - HTMX リクエストにページ全体のレスポンスを返すと、UX が損なわれ、重複した HTML が送られます
- 部分テンプレートは自己完結した HTML フラグメントにします
必ず request.method を検証してください
- フォームデータを処理する前に、
request.method == "POST"を確認します - 適切なステータスコードを返します(メソッドが正しくない場合は 405 Method Not Allowed)
CSRF はすでにグローバルに設定されています
- ベーステンプレートの
<body>にhx-headersが設定されているため、個々のフォームに CSRF トークンを追加する必要はありません - すべての HTMX リクエストに CSRF トークンが自動的に含まれます
テンプレートの整理
命名規則
- 部分テンプレート:
_partial.html(先頭にアンダースコア) - ページ全体のテンプレート:
page.html(先頭に記号なし) - 例:
posts/list.html(ページ全体)にposts/_list.html(部分テンプレート)を含めます
構成
- ページ全体のテンプレートは
base.htmlを継承し、部分テンプレートを含めます - 部分テンプレートには動的な HTML フラグメントのみを記述します
- HTMX のターゲットには、部分テンプレートのコンテナー div を指定します
部分テンプレートの役割を絞ってください
- 各部分テンプレートは、1 つの論理的な UI コンポーネントを表すようにします
- 大きすぎる、または多くの処理を担う部分テンプレートは避けます
- 大きな UI は、複数の小さな部分テンプレートを組み合わせて構成します
Django ビューのパターン
HTMX の検出
HX-Request ヘッダーを確認して、HTMX リクエストを検出します。
def my_view(request):
context = {...}
if request.headers.get("HX-Request"):
return render(request, "app/_partial.html", context)
return render(request, "app/full_page.html", context)
フォーム処理のパターン
要点:
- 通常どおりフォームを検証します
- 成功時:新しいデータを含む部分テンプレートを返すか、クライアント側のイベントを発生させます
- エラー時:フォームエラーを含む部分テンプレートを返します
- HTMX と非 HTMX の両方のケースを必ず処理します
def create_view(request):
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
obj = form.save()
if request.headers.get("HX-Request"):
return render(request, "app/_item.html", {"item": obj})
return redirect("app:list")
# Return form with errors
if request.headers.get("HX-Request"):
return render(request, "app/_form.html", {"form": form})
else:
form = MyForm()
return render(request, "app/create.html", {"form": form})
レスポンスヘッダーのリファレンス
HTMX はクライアント側の動作に関する特別なレスポンスヘッダーを処理します。
HX-Trigger
レスポンスの後にクライアント側イベントを発生させます
- 使用例:操作の後にページの別の部分を更新する
- 例:
response["HX-Trigger"] = "itemCreated" - テンプレート側のリスナー:
<div hx-get="/count/" hx-trigger="itemCreated from:body">
HX-Redirect
クライアント側でリダイレクトします
- 使用例:操作の成功後にリダイレクトする
- 例:
response["HX-Redirect"] = reverse("app:detail", args=[obj.pk])
HX-Retarget / HX-Reswap
サーバー側から hx-target と hx-swap を上書きします
- 使用例:成功時とエラー時で異なるターゲットを使う
- 成功時:
response["HX-Retarget"] = "#main" - エラー時:ターゲットを変更せずに部分テンプレートを返します(フォームがターゲットになります)
HX-Refresh
ページ全体の再読み込みを強制します
- 使用例:ページ全体に影響する大きな状態変更
- 例:
response["HX-Refresh"] = "true"
よくある落とし穴
- 読み込みインジケーターの不足:必ず
hx-indicatorを使用してください。フィードバックがないと、ユーザーは複数回クリックしてしまいます。 - HTMX レスポンスに完全なページを返す:
base.htmlを含む完全なページではなく、_partial.htmlを返してください。HX-Requestヘッダーを確認します。 - フォームエラーへの未対応:検証に失敗した場合は、成功時だけでなく、エラーを含むフォームを必ず返してください。
- ボタンを無効化しない:重複送信を防ぐため、
hx-disabled-elt="this"を使用してください。 - N+1 クエリ:HTMX ビューでも、通常のビューと同様に
select_related()/prefetch_related()が必要です。
他のスキルとの連携
- django-templates:部分テンプレートの構成と継承パターン
- django-forms:HTMX によるフォーム送信と検証
- django-extensions:
show_urlsを使用して HTMX エンドポイントを確認します。 - pytest-django-patterns:HTMX エンドポイントとヘッダーのテスト
- systematic-debugging:HTMX のリクエスト/レスポンスに関する問題のデバッグ
コメント
Markdown 対応