# 使用Django和HTMX简化动态Web开发(第四部分):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`究竟是以何种方式向服务器发送数据的?由于许多示例只展示了非常简单的功能,要找到创建和发送复杂数据负载的实际案例却出乎意料地困难。 本文将彻底梳理HTMX中的数据传输方式以及服务器如何处理这些数据。 ![Django中HTMX数据流示意图](/media/whitedec/blog_img/fbe9c41ba8ea4eabb78e760e1f768482.webp) ------ ## HTMX的数据传输方式 {#sec-1f930b1a0dad} `fetch`的数据负载处理方式与`hx-post`的数据传输方式存在显著差异。 在`fetch`中,开发者需要手动创建对象并将其转换为JSON格式放入请求体(body)。而**HTMX则默认收集DOM中的值并进行传输**。 HTMX的思维方式更接近于**“从HTML元素中收集值来构建请求参数”**,而非“直接组装JS对象”。通常,它采用以下三种方式: ### 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 Payload”不同 {#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`接收,并**返回HTML片段而非JSON**——这正是HTMX最能发挥其优势的地方。 ### 但如果不想放弃DRF序列化器的便利性怎么办? {#sec-2a26aeec3b61} DRF的序列化器确实非常强大。难道仅仅因为使用了HTMX,就必须放弃这个便捷的验证工具,转而进行`request.POST.get()`的繁琐操作吗? 幸运的是,DRF序列化器不仅能出色地验证JSON,也能很好地验证表单数据。由于这部分内容较长,我们将在下一篇文章中深入探讨**“HTMX与DRF序列化器的共存之道”**。 ------ ## 总结 {#sec-ab81cf195815} 今天的文章内容总结如下: 1. **HTMX默认从DOM中收集值。**这与`fetch`直接构建数据负载对象的方式有所不同。 2. **三种传输方式:**用于发送整个表单的``,用于选择性发送的`hx-include`,以及用于添加额外值的`hx-vals`。 3. **默认是表单数据。**请注意,`hx-vals`使用JSON语法并不意味着它会发送实际的JSON请求体。 4. **如果确实需要JSON,请使用`json-enc`扩展。**但最好记住,HTMX的真正精髓在于交换HTML片段。 下一次,我们将探讨如何将DRF的便利性融入HTMX中! **相关文章阅读** - [使用Django和HTMX简化动态Web开发(第一部分)](/ko/whitedec/2025/1/27/django-htmx-dynamic-web-simplification/) - [使用Django和HTMX简化动态Web开发 - Ajax (第二部分)](/ko/whitedec/2025/1/27/django-htmx-dynamic-web-simplification-2/) - [使用Django和HTMX简化动态Web开发(第三部分):Django集成方法](/ko/whitedec/2025/1/27/django-htmx-dynamic-web-simplification-3/) - [使用Django和HTMX简化动态Web开发(第五部分)](/ko/whitedec/2025/1/27/django-htmx-advanced-features/) - [使用Django和HTMX简化动态Web开发(第六部分):HTML返回方式](/ko/whitedec/2025/1/27/django-htmx-html-response/) - [使用Django和HTMX简化动态Web开发(第七部分):JSON返回方式](/ko/whitedec/2025/1/27/django-htmx-json-response/)