news 2026/6/24 4:20:22

Flask 笔记四:用 WTForms 做新增、编辑和删除

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flask 笔记四:用 WTForms 做新增、编辑和删除

1. 为什么不用原生<form>

之前的写法:

title = request.form.get("title")

if not title:

flash("标题不能为空")

能工作,但页面一多就会重复很多类似代码。Flask-WTF 帮你集中处理:

能力原生表单Flask-WTF

必填校验

自己写 if

DataRequired()

错误提示

自己 flash

form.title.errors

CSRF 防伪造

没有

自动带csrf_token

编辑页回填

手动赋值

form.title.data = row.title

入门项目用 WTForms,后面会省很多事。


2. 安装 Flask-WTF

pip install Flask-WTF

app/__init__.py里已有SECRET_KEY,WTForms 会用它生成 CSRF token,不用额外配置。


3. 定义表单:app/forms.py

新建文件,写NoteForm

from flask_wtf import FlaskForm

from wtforms import StringField, TextAreaField, SubmitField

from wtforms.validators import DataRequired, Length, Optional

class NoteForm(FlaskForm):

title = StringField(

"标题",

validators=[

DataRequired("请输入标题"),

Length(max=100, message="标题最多 100 个字"),

],

)

content = TextAreaField(

"内容",

validators=[Optional()],

)

submit = SubmitField("保存")

几个常用校验器:

  • DataRequired— 不能为空
  • Length(max=100)— 长度限制
  • Optional— 可以为空

4. 改造「新增」页面

视图app/home/views.py

from flask import render_template, redirect, url_for, flash

from app import db

from app.home import home

from app.forms import NoteForm

from app.models import Note

@home.route("/notes/add/", methods=["GET", "POST"])

def note_add():

form = NoteForm()

if form.validate_on_submit():

note = Note(

title=form.title.data.strip(),

content=(form.content.data or "").strip(),

)

db.session.add(note)

db.session.commit()

flash("保存成功")

return redirect(url_for("home.note_list"))

return render_template("home/note_form.html", form=form, title="新增备忘录")

和之前学习的form的区别:

  • form.validate_on_submit()代替手写的if not title
  • 校验失败时,表单会保留用户已填的内容

模板app/templates/home/note_form.html

新增和编辑共用这一个模板:

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>{{ title }}</title>

</head>

<body>

<h1>{{ title }}</h1>

{% with messages = get_flashed_messages() %}

{% for msg in messages %}

<p style="color:green;">{{ msg }}</p>

{% endfor %}

{% endwith %}

<form method="post">

{{ form.csrf_token }}

<p>

{{ form.title.label }}<br>

{{ form.title(size=40) }}

{% for err in form.title.errors %}

<span style="color:red;">{{ err }}</span>

{% endfor %}

</p>

<p>

{{ form.content.label }}<br>

{{ form.content(rows=5, cols=40) }}

{% for err in form.content.errors %}

<span style="color:red;">{{ err }}</span>

{% endfor %}

</p>

<p>{{ form.submit }}</p>

<a href="{{ url_for('home.note_list') }}">返回列表</a>

</form>

</body>

</html>

别忘了{{ form.csrf_token }},漏了 POST 会 400 报错。


5. 做「编辑」页面

编辑和新增逻辑很像:GET 时把数据库里的值填进表单,POST 时更新。

@home.route("/notes/edit/<int:note_id>/", methods=["GET", "POST"])

def note_edit(note_id):

row = Note.query.get_or_404(note_id)

form = NoteForm()

if request.method == "GET":

form.title.data = row.title

form.content.data = row.content

if form.validate_on_submit():

row.title = form.title.data.strip()

row.content = (form.content.data or "").strip()

db.session.commit()

flash("修改成功")

return redirect(url_for("home.note_list"))

return render_template(

"home/note_form.html",

form=form,

title="编辑备忘录",

)

get_or_404(note_id):找不到记录就返回 404,不用自己写 if。


6. 做「删除」

删除不要用 GET(链接一点就删,不安全)。用 POST + 单独的小表单。

表单app/forms.py里加一行

class DeleteForm(FlaskForm):

submit = SubmitField("确认删除")

也可以只放csrf_token,不显示 submit 按钮,用 JS 提交;入门阶段这样写最直观。

视图

from app.forms import NoteForm, DeleteForm

@home.route("/notes/delete/<int:note_id>/", methods=["POST"])

def note_delete(note_id):

row = Note.query.get_or_404(note_id)

form = DeleteForm()

if form.validate_on_submit():

db.session.delete(row)

db.session.commit()

flash("已删除")

return redirect(url_for("home.note_list"))

列表页里加编辑 / 删除

更新app/templates/home/note_list.html

{% for note in page_data.items %}

<div class="item">

<h3>{{ note.title }}</h3>

<p>{{ note.content or '(无内容)' }}</p>

<div class="time">{{ note.addtime.strftime('%Y-%m-%d %H:%M') }}</div>

<p>

<a href="{{ url_for('home.note_edit', note_id=note.id) }}">编辑</a>

<form method="post"

action="{{ url_for('home.note_delete', note_id=note.id) }}"

style="display:inline;">

{{ delete_form.csrf_token }}

<button type="submit" οnclick="return confirm('确定删除?')">删除</button>

</form>

</p>

</div>

{% endfor %}

列表视图里多传一个delete_form

from app.forms import DeleteForm

@home.route("/notes/")

def note_list():

page = request.args.get("page", 1, type=int)

page_data = Note.query.order_by(Note.addtime.desc()).paginate(

page=page, per_page=10,

)

return render_template(

"home/note_list.html",

page_data=page_data,

delete_form=DeleteForm(),

)


7. 一张图串起来

列表页 /notes/

├─ 新增 → /notes/add/ → NoteForm → db.session.add

├─ 编辑 → /notes/edit/1/ → NoteForm → 改 row 字段 → commit

└─ 删除 → POST /notes/delete/1/ → DeleteForm → db.session.delete

到这一步,一个最小的 增删改查 就齐了。


8. 新手常踩的 4 个坑

坑 1:模板里漏了csrf_token

报错类似The CSRF token is missing
每个 POST 表单都要有{{ form.csrf_token }}

坑 2:只写form.validate(),没写validate_on_submit()

validate_on_submit()= 「这次是 POST 提交 并且 校验通过」。
GET 打开页面时不应触发写入逻辑。

坑 3:编辑页 GET 和 POST 混在一个 if 里

推荐顺序:

if request.method == "GET":

form.title.data = row.title # 先回填

if form.validate_on_submit(): # 再处理提交

...

坑 4:删除用 GET 链接

<!-- 不要这样 -->

<a href="/notes/delete/1/">删除</a>

爬虫、预加载都可能误触。删除务必 POST。


9. 和真实项目的关系(不写细节,只讲习惯)

实际项目里常见做法和这篇一致:

  • 一个XxxForm管新增和编辑
  • validate_on_submit()add或改row
  • 删除单独 POST,带 CSRF
  • 模板里循环form.xxx.errors显示错误

复杂表单会加SelectFieldDateField、自定义validate_xxx,但套路不变。


10. 小结

这一篇核心三件事:

  1. 表单类 — 字段 + 校验规则写在一起
  2. validate_on_submit()— 统一的「提交且合法」入口
  3. CSRF — 每个 POST 表单都要 token

三篇连起来,你已经会:

内容

项目结构、Blueprint

数据库、列表、分页

WTForms、编辑、删除


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/24 4:06:47

Hermes Agent 一周暴涨五万 Star,但我劝你别急着追

一周五万 Star&#xff0c;发生了什么 上周打开 GitHub Trending 周榜&#xff0c;我盯着第二名的数字看了三遍&#xff1a; NousResearch/hermes-agent — 一周 53,110 Star&#xff0c;总 Star 91.1K。 两个月不到&#xff0c;从建仓到九万星。这个增长速度意味着什么&…

作者头像 李华
网站建设 2026/6/24 4:05:43

当游戏成就变成可编程的艺术:Xbox成就解锁器的逆向工程之旅

当游戏成就变成可编程的艺术&#xff1a;Xbox成就解锁器的逆向工程之旅 【免费下载链接】Xbox-Achievement-Unlocker Achievement unlocker for xbox games (barely works but it does) 项目地址: https://gitcode.com/gh_mirrors/xb/Xbox-Achievement-Unlocker 想象一下…

作者头像 李华
网站建设 2026/6/24 4:03:33

别再用旧犀牛!Rhino8.30最新版本 完整版安装教程

一、Rhino8.3简介 Rhino8.30 是犀牛 8 系列稳定修复版&#xff0c;轻量化三维曲面建模软件&#xff0c;Windows、Mac 双平台通用。一次买断终身使用&#xff0c;小版本更新免费&#xff0c;普通笔记本就能流畅运行。支持 NURBS 精准曲面、SubD 细分、网格、点云四种建模模式&a…

作者头像 李华
网站建设 2026/6/24 4:02:55

开源版Figma:Penpot,设计协同+代码生成,全栈设计平台

设计师用浏览器画界面&#xff0c;开发者直接拿代码 支持自托管、实时协同、设计令牌 MCP服务器让AI也能参与设计&#x1f58c;️ 先看痛点&#xff1a;设计和开发之间&#xff0c;为什么总有“翻译偏差”&#xff1f; 你是一个产品团队的成员。 设计师在Figma里画好了一个精美…

作者头像 李华