# 使用 Django 和 HTMX 簡化動態網頁開發 (第四篇): Payload 如何傳輸? 在使用傳統 JavaScript 的 `fetch` 進行 Ajax 請求時,發送 POST 請求通常會使用 `JSON.stringify()` 直接組裝 Payload。 大致的感覺如下: ```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` 究竟會以何種方式將資料發送到伺服器?由於許多範例只展示了非常簡單的功能,導致很難找到建立複雜 Payload 並發送的實際範例。 在這篇文章中,我們將完整整理 HTMX 的資料傳輸方式以及伺服器如何處理這些資料。 ![DJANGO 中 HTMX 資料流的示意圖](/media/whitedec/blog_img/fbe9c41ba8ea4eabb78e760e1f768482.webp) ------ ## HTMX 的資料傳輸方式 {#sec-1f930b1a0dad} **`fetch` 的 Payload 概念與 `hx-post` 的資料傳輸方式大相徑庭。** `fetch` 中,開發者直接建立物件並將其轉換為 JSON 放入 body。然而,**HTMX 基本上會從 DOM 中收集數值並進行傳輸**。 HTMX 的思維模式並非「直接組裝 JS 物件」,而是更接近於「**從 HTML 元素中收集數值以建立請求參數**」。為此,通常會採用以下三種方式: ### 1) 基於 Form 收集數值並發送 {#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) 不使用 Form 但包含其他元素的值: `hx-include` {#sec-a2c0e1f9e1ca} 當您希望在一個按鈕上附加 `hx-post`,並同時選擇性地包含其他位置的輸入值時,可以使用此方法。 ```HTML ``` `hx-include` 會將指定元素的數值包含在請求中。即使沒有用 `
` 包裹整個內容,也能產生類似 Payload 的結果,對於輸入項目較少的情況非常有用。 ### 3) 添加隱藏值或計算值: `hx-vals` {#sec-f3e44212771a} 這項功能最接近 `fetch` 中直接建立部分 Payload 物件的概念。 ```HTML ``` `hx-vals` 會在請求中添加額外參數。預設使用上述的 JSON 語法,但如果加上 `js:` 前綴,也可以發送動態的 JavaScript 計算值。 ```HTML ``` 在這種情況下,Django 仍然會透過 `request.POST` 讀取。因為 `hx-vals` 只是**「以類似 JSON 的語法定義數值」**,而非將請求主體本身轉換為 JSON。 ------ ## 注意事項: `hx-vals` 與「JSON Payload」不同 {#sec-c31077e0c2ea} 這是初次接觸 HTMX 時最容易混淆的部分。 ```HTML ``` 至此,我們才真正實現了熟悉的 JSON Payload 傳輸方式。此時,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` 接收,並**返回 HTML 片段而非 JSON**。這正是 HTMX 最能發光發熱的地方。 ### 但如果 DRF 序列化器不捨放棄怎麼辦? {#sec-2a26aeec3b61} DRF 的序列化器確實非常強大。難道因為使用 HTMX,就必須放棄這個方便的驗證工具,轉而進行 `request.POST.get()` 的繁瑣操作嗎? 幸運的是,DRF 序列化器不僅能對 JSON 進行驗證,也能出色地驗證表單資料。由於這部分內容較長,我們將在下一篇文章中深入探討**「HTMX 與 DRF 序列化器的共存」**。 ------ ## 總結 {#sec-ab81cf195815} 今日內容摘要如下: 1. **HTMX 基本上會從 DOM 中收集數值。** 其方法與直接組裝 Payload 物件的 `fetch` 不同。 2. **三種傳輸方式:** 發送全部內容的 ``、選擇性發送的 `hx-include`、以及添加數值的 `hx-vals`。 3. **預設為表單資料。** 請注意,`hx-vals` 雖然使用 JSON 語法,但實際上並非以 JSON body 形式傳輸。 4. **如果確實需要 JSON,請使用 `json-enc` 擴充功能。** 但請記住,HTMX 的核心優勢在於交換 HTML 片段。 下一回,我們將探討如何將 DRF 的便利性融入 HTMX! **相關閱讀** - [使用 Django 和 HTMX 簡化動態網頁開發 (第一部)](/ko/whitedec/2025/1/27/django-htmx-dynamic-web-simplification/) - [使用 Django 和 HTMX 簡化動態網頁開發 - Ajax (第二部)](/ko/whitedec/2025/1/27/django-htmx-dynamic-web-simplification-2/) - [使用 Django 和 HTMX 簡化動態網頁開發 (第三部):Django 整合方法](/zh-hant/whitedec/2025/1/27/django-htmx-dynamic-web-simplification-3/) - [使用 Django 和 HTMX 簡化動態網頁開發 (四): Payload 傳輸方式](/zh-hant/whitedec/2025/1/27/django-htmx-csrf-token-integration/) - [使用 Django 和 HTMX 簡化動態網頁開發:Form 與 Serializer 的應用](/zh-hant/whitedec/2026/4/22/django-htmx-forms-serializer-usage/) - [使用 Django 與 HTMX 簡化動態網頁開發:觸發器(Trigger)應用指南](/zh-hant/whitedec/2026/4/23/django-htmx-dynamic-web-development-trigger/)