需手动调用c.flashparams()保存表单值并模板中用{{.flash.xxx}}回填;复选框/多选需转布尔或切片传参判断checked/selected;须确保parseform成功且无中间件干扰body。

表单重定向后输入值全丢了,怎么让 value 回填?
Revel 不会自动把用户刚输的内容塞回模板的 input 里,必须手动触发保存。核心就两步:服务端存参数 + 模板里取值。
控制器验证失败后,必须立刻调用 c.FlashParams(),它会把当前请求所有表单字段(c.Request.Form)序列化进 Flash cookie。不调这句,.flash.username 在模板里永远是空的。
模板中写法要严格对应:
<input name="username" value="{{.flash.username}}">- 不能写成
{{.params.username}}或{{.username}}—— 那些是原始请求上下文,重定向后已失效 -
.flash是 Flash cookie 解析后的 map,只在重定向后的 GET 请求中可用
.flash 为什么有时取不到值?
常见原因有三个,按发生频率排序:
- 没在验证失败后调
c.FlashParams(),或调用了但前面漏了c.Validation.Keep()(Flash 依赖 Validation 的持久化机制) - 前端提交时用了
application/json而非application/x-www-form-urlencoded,导致c.Request.Form为空,c.FlashParams()实际没存任何东西 - 字段名大小写不一致:HTML 中是
name="Email",模板却写{{.flash.email}},Go map key 区分大小写
调试时可加一行 revel.INFO.Printf("Flash keys: %+v", c.Flash) 看实际存了哪些 key。
复选框(checkbox)和多选下拉(select multiple)怎么保持状态?
这类控件的“已选中”不是靠 value 属性决定的,而是靠是否存在 checked 或 selected 属性。所以不能只靠 .flash.xxx 填 value。
正确做法是:在控制器里把原始提交值转成布尔或字符串切片,再传给模板做判断:
- 单个 checkbox:
c.RenderArgs["is_subscribed"] = c.Params.Get("is_subscribed") == "on",模板中写<input type="checkbox" name="is_subscribed" .is_subscribed> - 多选下拉:
tags := c.Request.Form["tags"](先ParseForm),然后传c.RenderArgs["selected_tags"] = tags,模板中循环比对:{{range $.selected_tags}}{{if eq . "go"}}selected{{end}}{{end}}
注意:不要直接用 .flash.tags,因为它是字符串,不是切片,无法遍历。
为什么 .flash 有时只保留部分字段?
根本原因是 c.FlashParams() 只保存 c.Request.Form 中的键值对,而这个 map 的内容取决于请求是否被正确解析。
两个硬性前提必须满足:
- POST/PUT 请求必须显式调用
c.Request.ParseForm()(或ParseMultipartForm),否则c.Request.Form是 nil,c.FlashParams()什么也存不了 - 如果用了自定义中间件修改了
c.Request.Body(比如日志中间件读了一次 body),会导致后续ParseForm失败,c.Request.Form为空
最稳妥的做法:在验证逻辑前加一句 if err := c.Request.ParseForm(); err != nil { return c.RenderError(...) },别依赖框架自动解析。











