Revel详情页核心是复用布局、正确传入单条数据、避免c.Params.Route取ID失败;Show方法须查库并校验,模板用{{with .}}安全渲染,路由路径必须严格匹配{id}占位符。

Revel 模板做详情页,核心不是写新 HTML,而是复用布局 + 正确传入单条数据 + 避免 c.Params.Route 取 ID 失败导致 404 或空渲染。
用 Show 方法加载单条数据并传给模板
详情页本质是「根据 URL 中的 ID 查一条记录并展示」,必须在控制器里完成查询,不能靠前端拼接或模板里调 DB。Revel 的 CRUD 生成器默认会建 Show 方法,但需确认它真正执行了查询:
-
Show方法签名应为func (c App) Show(id string) revel.Result,注意参数是string类型(Revel 自动从路由 {id} 提取) - 方法体内必须调用类似
c.DB.Select(&user, "SELECT * FROM users WHERE id = ?", id)或 ORM 查询,不能只写return c.Render(user)却没查库 - 若用 Gorp,记得检查
user.ID是否已转为 int64,否则Get()可能静默失败 - 查不到时应显式返回
c.NotFound("User not found"),而不是让模板渲染 nil 结构体——后者会导致{{.Name}}全部为空且无报错
模板里用 {{with .}} 安全访问字段
直接写 {{.Name}} 在数据为空时会渲染空白,且不报错;用 {{with .}} 可包裹整个详情区块,既避免空指针风险,又让结构清晰:
{{with .}}
<h1>{{.Nickname}}</h1>
<p>邮箱:{{.Email}}</p>
<p>注册时间:{{.CreatedAt | date "2006-01-02"}}</p>
{{else}}
<p class="error">未找到该用户</p>
{{end}}-
{{with .}}的点号代表控制器传入的顶层数据(比如一个*models.User),它会把上下文切换到该对象,内部可直接写{{.Nickname}} -
date是 Revel 内置模板函数,格式字符串必须用 Go 时间常量风格("2006-01-02"),写成"Y-m-d"会失效 - 不要在
{{with}}外写字段引用,比如{{.ID}}放在{{with .}}上方,会被忽略
路由和 URL 路径必须匹配 {id} 占位符
Revel 不支持 Rails 风格的 /users/123 自动映射,路径定义和控制器方法签名必须严格一致:
- conf/routes 中必须写明:
GET /users/{id} App.Show—— 缺少{id}或写成/users/:id都会导致参数无法注入 - 浏览器访问时 URL 必须是
/users/42,不能是/users?id=42(那是 query 参数,c.Params.Route.Get("id")拿不到) - 如果用了自定义路由(如
GET /u/{uid}),控制器方法就得改成func (c App) Show(uid string),变量名必须和占位符一致 - 开发时可用
revel run启动后访问/routes查看当前有效路由表,确认{id}是否被正确识别
最容易被忽略的是:Show 方法里没做非空校验就直接传 struct 指针给模板,结果数据库查不到时传的是零值 struct,页面看似“渲染成功”实则全是空字段——这种问题不会报错,只能靠日志或手动加 {{printf "%#v" .}} 打印调试。


















