Go模板中的请求上下文

时间:2013-08-18 19:24:10

标签: templates go

我想在Go HTML template中编写这样一个条件片段:

  {{if isUserAdmin}}
     <a href"/admin/nuke">Go to the big red nuclear button</a>
  {{end}}

但是,这不是直接可行的,因为模板不知道触发其执行的request,因此无法确定用户是否是管理员。

有没有一些正常的方法来实现这个目标?

事先我指出:

  • 我不想对此特定数据使用Pipelines(请参阅other question有关此内容)
  • 我承认只有处理程序/控制器才能处理逻辑,而视图应该只进行渲染。但条件{{if isUserAdmin}}本身不是逻辑,它是利用控制器已经计算的布尔值的必要结构。
  • Funcs方法可以提供帮助,但目前还不够精简,无法轻松定义具体方法isUserAdmin()

3 个答案:

答案 0 :(得分:3)

这是working solution attempt (link to Playground)使用Funcs覆盖"isAdmin",在模板编译后但在每次执行之前(感谢other question中的Valentin CLEMENT)。

但它有几个缺陷:

  • 在模板编译之前声明一个虚拟的空"isAdmin"函数是很奇怪的。
  • 多次使用Func是痛苦的,因为我不能只覆盖一个方法,我必须提供一个完整的FuncMap所有函数)编辑:实际上以前的函数不是丢了,我错了。
  • 它本身就不是线程安全的,并且当几个goroutine改变并执行相同的模板时会失败

答案 1 :(得分:3)

正常的做法是简单地将模板传递给您喜欢的任何静态数据。除非我误解了你想要做的事情,否则Funcs似乎没有任何需要。简化你的例子:

package main

import (
    "html/template"
    "os"
)

const hometmpl = `
{{if .IsAdmin}}
  <a href="/admin/nuke">Go to the big red nuclear button</a>
{{end}}
`

var t = template.Must(template.New("home").Parse(hometmpl))

func isAdmin(token string) bool {
    const adminToken = "0xCAFEBABE"
    return token == adminToken
}

func main() {
    token := "0xCAFEBABE" // Or extracted from the http.Request
    t.ExecuteTemplate(os.Stdout, "home", struct{IsAdmin bool}{isAdmin(token)})
}

答案 2 :(得分:3)

我同意Darshan Computing的观点,我认为从请求中传递信息的正确方法是在管道中。您可以在要渲染的数据和上下文之间拆分数据,例如:通过让你的模板数据结构嵌入它们,如果你想明确区分两者:

type TemplateData struct {
    *Content
    *Context
}

例如,this。然后,您可以重复使用某些上下文/内容信息,具体取决于共享内容和查询特定内容。