4

我想在 Go HTML 模板中编写这样的条件片段:

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

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

有没有一些正常的方法来实现这一点?

我提前指出:

  • 我不想将管道用于此特定数据(请参阅有关此的其他问题
  • 我承认只有处理程序/控制器应该处理逻辑,而视图应该只进行渲染。但是条件{{if isUserAdmin}}本身并不是逻辑,它是利用控制器已经计算的布尔值的必要结构。
  • Funcs方法可以提供帮助,但目前还不足以轻松定义特定方法isUserAdmin()
4

3 回答 3

4

我同意 Darshan Computing,我认为从请求中传递信息的正确方法将在管道中。您可以将数据在要呈现的数据和上下文之间进行拆分,例如,如果您想清楚地将两者分开,可以将它们都嵌入模板数据结构中:

type TemplateData struct {
    *Content
    *Context
}

例如,这给出了这个。然后,您可以根据共享的内容和特定查询的内容重用您的一些上下文/内容信息。

于 2013-08-19T08:44:02.290 回答
3

Here is a working solution attempt (link to Playground) using Funcs to overwrite "isAdmin", after template compilation but before each execution (thanks to Valentin CLEMENT in other question).

But it has several flaws :

  • It is weird to declare a dummy empty "isAdmin" function before template compilation.
  • (Using Funcs several times is painful because I cannot just overwrite a single method, I have to provide a complete FuncMap with all the functions) edit : in fact previous funcs are not lost, i was wrong about that.
  • It is inherently not thread-safe and will fail when several goroutines alter and execute the same template
于 2013-08-18T19:27:26.503 回答
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)})
}
于 2013-08-19T06:49:42.533 回答