# DjangoとHTMXで動的Web開発をシンプルに(第4回):ペイロードはどのように送る? 従来のJavaScriptの`fetch`を使ったAjaxリクエストでは、POSTリクエストを送信する際、通常`JSON.stringify()`を使ってペイロードを直接組み立てて送ります。 おおよそこのようなイメージです。 ```JavaScript fetch("/api/todos/", { method: "POST", headers: { "Content-Type": "application/json", "X-CSRFToken": csrftoken }, body: JSON.stringify({ title: "買い物", done: false, priority: 3 }) }) ``` では、**[[HTMX]]**ではどうでしょうか?一体`hx-post`はどのような方法でデータをサーバーに送信するのでしょうか?多くの例がごくシンプルな機能しか示していないため、複雑なペイロードを作成して送信する実践的な例を見つけるのは意外と困難です。 今回の記事では、HTMXにおけるデータ送信方法と、サーバーでそれを処理する方法を完全にまとめます。 ![DJANGOにおけるHTMXデータのフロー図](/media/whitedec/blog_img/fbe9c41ba8ea4eabb78e760e1f768482.webp) ------ ## HTMXのデータ送信方法 {#sec-1f930b1a0dad} **`fetch`のペイロード感覚と`hx-post`のデータ送信方法はかなり異なります。** `fetch`では、開発者が直接オブジェクトを作成し、JSONに変換してボディに格納します。一方、**HTMXは基本的にDOMにある値を収集して送信します。** [[HTMX]]の考え方は、「JSオブジェクトを直接組み立てる」のではなく、**「HTML要素から値を集めてリクエストパラメータを作成する」**ことに近いです。通常、これには以下の3つの方法を使用します。 ### 1) フォームベースで値を集めて送信する {#sec-f5086851ac19} 最もHTMLらしく、Djangoにもよく合う方法です。 ```html
``` この場合、[[HTMX]]はフォーム内の入力値を収集し、リクエストに含めて送信します。デフォルトのエンコーディングは、通常のフォーム送信と同じ**URL-encoded form data**方式です。 Djangoビューでは、普段通りに次のように受け取ることができます。 ```Python def create_todo(request): title = request.POST.get("title") priority = request.POST.get("priority") done = request.POST.get("done") ``` ### 2) フォームを使わず他の要素の値を含める:`hx-include` {#sec-a2c0e1f9e1ca} ボタン一つに`hx-post`を付け、離れた場所にある特定の入力値だけを一緒に送りたい場合に使用します。 ```HTML ``` `hx-include`は指定した要素の値をリクエストに含めます。わざわざ全体を`
`で囲まなくてもペイロードと似た結果を作成できるため、入力項目が少ない場合に非常に便利です。 ### 3) 隠し値や計算された値を追加する:`hx-vals` {#sec-f3e44212771a} これが、`fetch`でペイロードオブジェクトの一部を直接作成する概念に最も近い機能です。 ```HTML ``` `hx-vals`はリクエストに追加のパラメータを挿入します。デフォルトは上記のようにJSON構文を使用しますが、`js:`プレフィックスを付けると動的なJavaScript計算値も送信できます。 ```HTML ``` この場合もDjangoでは`request.POST`で読み取ります。`hx-vals`は**「JSONのような構文で値を定義する」**ものであり、リクエストボディ自体をJSONにするわけではないためです。 ------ ## 注意点:`hx-vals`は「JSONペイロード」とは異なります {#sec-c31077e0c2ea} [[HTMX]]を初めて触る際に最も混乱しやすい部分です。 ```HTML ``` これでようやく、私たちが慣れ親しんだJSONペイロード方式になります。このとき、Djangoビューでは`request.POST`が空になるため、`request.body`を直接読み取る必要があります。 ```Python import json def create_todo_api(request): data = json.loads(request.body) title = data.get("title") # ... ロジック処理 ... return JsonResponse({"ok": True}) ``` ------ ## [[HTMX]]とDRFは哲学のギャップがあるが、無理に統合する必要もない {#sec-aff378931c81} 拡張パックを使ってJSONを送信することはできますが、それがHTMXらしい方法なのかという疑問は残ります。これは**「データ中心(DRF)」**と**「ハイパーメディア中心(HTMX)」**という二つの哲学が衝突する点だからです。 HTMXを適切に使うと決めたのであれば、もしかしたらデータ中心の考え方から一時的に離れる必要があるかもしれません。``、`hx-include`、`hx-vals`で値を送信し、サーバーは`request.POST`でそれを受け取り、**JSONではないHTMLスニペットを返す**こと。それ自体がHTMXが最も輝くポイントです。 ### しかし、DRFシリアライザーを諦めるのはもったいない? {#sec-2a26aeec3b61} DRFのシリアライザーは本当に強力です。HTMXを使うからといって、この便利なバリデーションツールを捨てて`request.POST.get()`で手動で処理しなければならないのでしょうか? 幸いなことに、DRFシリアライザーはJSONだけでなくフォームデータも非常にうまく検証してくれます。この部分は内容が長くなりそうなので、次回**「HTMXとDRFシリアライザーの共存」**について深く掘り下げていきたいと思います。 ------ ## まとめ {#sec-ab81cf195815} 今日のまとめは以下の通りです。 1. **[[HTMX]]は基本的にDOMから値を収集します。** 直接ペイロードオブジェクトを構築する`fetch`とはアプローチが異なります。 2. **送信方法は3種類:** 全体を送る``、選んで送る`hx-include`、値を追加する`hx-vals`。 3. **基本はフォームデータです。** `hx-vals`がJSON構文を使うからといって、実際のJSONボディとして送信されるわけではないので注意してください。 4. **JSONがどうしても必要なら`json-enc`拡張を使いましょう。** しかし、HTMX本来の醍醐味はHTMLの断片をやり取りすることにある、と覚えておくと良いでしょう。 次回は、DRFの利便性をHTMXに組み込む方法についてお届けします! **関連記事** - [DjangoとHTMXで動的Web開発をシンプルにする(パート1)](/ja/whitedec/2025/1/27/django-htmx-dynamic-web-simplification/) - [DjangoとHTMXで動的ウェブ開発をシンプルに - Ajax(第2回)](/ja/whitedec/2025/1/27/django-htmx-dynamic-web-simplification-2/) - [DjangoとHTMXで動的ウェブ開発をシンプルに (第3回): Djangoへの統合方法](/ja/whitedec/2025/1/27/django-htmx-dynamic-web-simplification-3/) - [DjangoとHTMXで動的Web開発をシンプルに(第4回):ペイロードの送信方法](/ja/whitedec/2025/1/27/django-htmx-csrf-token-integration/) - [DjangoとHTMXで動的Web開発をシンプルに:FormとSerializerの活用法](/ja/whitedec/2026/4/22/django-htmx-forms-serializer-usage/) - [DjangoとHTMXで動的ウェブ開発をシンプルに:Triggerの活用法](/ja/whitedec/2026/4/23/django-htmx-dynamic-web-development-trigger/)