在现代化的 Web 开发中,前后端分离架构已成为主流。传统的 Django 开发者习惯使用 Form 或 ModelForm 来处理表单的渲染与校验,但在前后端分离的场景下,这些职责被重新划分。本文将以我开发的个人主页系统中的项目管理模块为例,解析如何通过 React 搭配 Django REST Framework (DRF) 实现一套高可用、带严格校验的进阶版表单系统。
一、 功能演示
本表单模块主要用于后台管理系统中"项目 (Project)"的发布与编辑。
- 前端组件设计:采用 React 受控组件构建抽屉式 (Drawer) 表单。输入状态被实时接管,确保数据的双向绑定,提供丝滑的输入体验。
- 字段校验规则 :前端通过 React 的
useMemo进行基础校验(如标题、slug必填等非空判断);后端由 DRF 的ModelSerializer依据数据库模型(如max_length=200,unique=True)自动执行深度校验,替代了传统的ModelForm。 - 防重复提交策略 :前端动态监测输入有效性,条件不足时禁用(
disabled)保存按钮,从源头防止无效点击。若发生网络延迟,配合 Loading 状态锁定操作;同时后端数据库依靠唯一性约束作为最后一道防线,防止脏数据写入。

二、 核心代码
1. 后端校验:DRF 的 ModelSerializer
在前后端分离架构中,DRF 的 ModelSerializer 完美接管了传统 ModelForm 的数据验证与持久化工作。它通过反射模型定义,自动生成严谨的校验规则。
python
# portfolio/models.py
from django.db import models
class Project(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=220, unique=True) # 数据库层面保证唯一性,防止重复
is_published = models.BooleanField(default=True)
# ... 省略其他字段
# portfolio/serializers.py
from rest_framework import serializers
from .models import Project
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = "__all__" # 自动映射并生成深层验证规则
2. 前端交互:React 表单提交与异常捕获
前端在提交数据时,不仅要处理正常流程,还需要优雅地解析后端 ModelSerializer 返回的字段级错误,并将其转换为用户友好的提示。
tsx
// frontend/src/pages/admin/ProjectsManager.tsx
const onSave = async () => {
if (!canSave) return; // 基础防重复/空数据拦截
try {
const payload = {
title: title.trim(),
slug: slug.trim(),
// ... 构建其余字段
};
if (editing) {
await updateProject(editing.id, payload); // 发送 PUT 请求
push({ title: "已更新项目", tone: "success" });
} else {
await createProject(payload); // 发送 POST 请求
push({ title: "已新增项目", tone: "success" });
}
setOpen(false); // 成功后关闭表单
} catch (err: any) {
// 核心逻辑:捕获并解析 DRF 返回的 400 Bad Request 验证错误
let msg = "保存失败,请检查输入";
if (err.response?.data) {
const errors = err.response.data;
const errMsgs = [];
for (const [key, val] of Object.entries(errors)) {
// 提取 DRF 序列化器抛出的具体字段错误
errMsgs.push(`${key}: ${Array.isArray(val) ? val[0] : val}`);
}
if (errMsgs.length > 0) msg = errMsgs.join(" | ");
}
push({ title: msg, tone: "error" }); // Toast 提示错误,例如 "slug: project with this slug already exists."
}
};


三、 验证接口
为了验证后端表单验证逻辑的健壮性,我们可以直接使用 Postman 对 API 进行调试。此处提供完整的调用示例,供读者一键复现。
- API 地址 :
http://127.0.0.1:8000/api/portfolio/projects/( - Method :
POST - Headers :
Content-Type: application/jsonAuthorization: Bearer <你的_JWT_TOKEN>
请求 Body (JSON):
json
{
"title": "测试项目",
"slug": "test-project",
"summary": "这是一个测试项目",
"sort_order": 1,
"is_published": true
}
预期响应 1:成功创建 (HTTP 201 Created)
json
{
"id": 1,
"title": "测试项目",
"slug": "test-project",
"is_published": true
}

预期响应 2:校验拦截 (HTTP 400 Bad Request)
若故意再次发送相同的 payload,DRF 会自动触发 unique=True 校验并拦截:
json
{
"slug": [
"project with this slug already exists."
]
}

四、 总结
通过上述可以看出,在现代化的 Web 项目中,虽然我们不再直接编写 Django 传统的 ModelForm 和 HTML 模板,但"表单验证"的核心思想从未改变。