## 使用 [[Django]] 和 HTMX 简化动态 Web 开发:Form 和 Serializer 的应用 {#sec-b233da7ff7c9} 在上一篇文章中,我们探讨了 **[[HTMX]] 将数据发送到服务器的方式**。 **回顾上一篇**:[使用 Django 和 HTMX 简化动态 Web 开发(第四部分):Payload 传输方式](/ko/whitedec/2025/1/27/django-htmx-csrf-token-integration/) 我们发现,如果说传统 JavaScript 的 `fetch()` 更接近于直接构建 JSON payload 并发送,那么 **HTMX 则更倾向于从 DOM 收集值并以 form-data 的形式发送**。 那么,一个自然而然的问题便浮现出来: **“对于 HTMX 传入的数据,Django 应该使用什么工具进行验证才最自然?”** 起初,许多人可能会想到 **DRF Serializer**。实际上,Serializer 确实是一个强大的验证工具,即使不是 JSON 数据也能使用。但当我们尝试将其与 HTMX 结合使用时,总会感觉有些格格不入。 这是为什么呢? 原因很简单: **HTMX 的基本工作流程更贴近 HTML 表单的世界,而 Django 中恰好已经存在专为此类场景设计的 `Form`。** 在本文中,我们将整理 **在 HTMX 请求处理中,`Django Form` 和 `DRF Serializer` 各自的用法**,并探讨 **哪种方案更为自然和实用**。  --- ## [[HTMX]] 发送的数据本质上更接近“表单数据” {#sec-8c911eee119a} 正如我们在上一篇中看到的那样,HTMX 默认会收集 HTML 元素的值并将其发送到服务器。这包括发送 `
``` 这个例子虽然很简单,但它很好地展示了 [[HTMX]] 和 Django Form 的完美结合。 * 失败时可以重新渲染整个表单 * 用户输入的值得以保留 * 错误消息自然地显示在字段旁边 如果采用传统的 `fetch()` + JSON + 手动 DOM 操作方式,实现这样的流程需要编写大量的 JavaScript 代码。但通过 HTMX 和 Django Form 的组合,仅需服务器端代码和模板就能以更简单的方式处理。 --- ## 那么,Serializer 就完全不需要了吗? {#sec-5f0d93fcd48a} 说**Serializer 完全不需要**可能有些言过其实,更准确的说法或许是:**没必要将 Serializer 作为默认选择**。您觉得呢? 实际上,[[DRF]] Serializer 在以下情况下仍然具有足够的吸引力: * 项目整体已积极使用 DRF * 希望在 API 和服务器渲染页面中重用相同的验证逻辑 * 输入验证逻辑复杂,且已在 Serializer 中良好组织 * 未来计划将相同功能暴露给移动应用或外部 API 也就是说,Serializer 的使用并非**“HTMX 是否能用?”** 的问题,而更接近于**“在这种特定场景下,引入 Serializer 是否能为整体架构带来益处?”** 的问题。 --- ## Serializer 也可以使用 {#sec-bfbe9c61b12c} 例如,假设您已经有以下 Serializer: ```python from rest_framework import serializers class TodoSerializer(serializers.Serializer): title = serializers.CharField(max_length=100) priority = serializers.IntegerField(min_value=1, max_value=5) ``` 在这种情况下,它在 HTMX 请求中也完全可以使用。 ```python from django.shortcuts import render def todo_create_with_serializer(request): if request.method == "POST": serializer = TodoSerializer(data=request.POST) if serializer.is_valid(): title = serializer.validated_data["title"] priority = serializer.validated_data["priority"] return render(request, "todos/partials/todo_item.html", { "title": title, "priority": priority, }) return render(request, "todos/partials/todo_form_serializer.html", { "errors": serializer.errors, "data": request.POST, }, status=400) ``` 如您所见,**技术上完全没有问题**。 Serializer 并非只能接收 JSON 数据。 然而,这里存在一些微妙的差异。 使用 Form 时: * 输入值保留 * 按字段渲染 * 错误绑定 * 与模板的连接 这些流程自然而然地衔接在一起。 而使用 Serializer 时: * 需要手动将 `serializer.errors` 适配到模板结构中 * 需要单独传递原始输入值 * 开发者需要更多地关注 HTML 表单重新渲染的连接 也就是说,**虽然可以使用,但会增加一些手动操作**。 正是因为这一点,当与 [[HTMX]] 结合使用时,Serializer 可能会让人感觉有些生硬。 --- ## 总结 {#sec-37e5d418cdb7} 在上一篇文章中,我们探讨了 [[HTMX]] 如何发送数据。而在本文中,我们总结了在 Django 中如何最自然地验证这些数据。 * HTMX 默认与 form-data 配合良好 * Django Form 正是为此流程设计的工具 * 因此,仅从与 HTMX 的兼容性来看,Form 是最自然的选择 * DRF Serializer 虽然可用,但更偏向于战略性的选择 我个人认为,要充分发挥 HTMX 的潜力,不仅需要**“以 HTML 方式处理 AJAX 的直觉”**,还需要**“重新找回利用 Django Form 和表单标签的直觉”**。 --- **相关阅读** * [使用 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 开发(第四部分):payload 是如何传输的?](/ko/whitedec/2025/1/27/django-htmx-advanced-features/)