【问题标题】:Request context in a Go templateGo 模板中的请求上下文
【发布时间】:2013-08-18 19:24:09
【问题描述】:

我想在 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()

【问题讨论】:

    标签: templates go


    【解决方案1】:

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

    type TemplateData struct {
        *Content
        *Context
    }
    

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

    【讨论】:

    • 是的,我目前在我的项目中使用这种方法。处理许多子模板时确实很麻烦:要么我的根管道是一个层次结构,其中包含具有很多冗余的结构(传递给子模板的每个数据都必须有自己的指向上下文的指针),或者如其他问题所述,必须通过多路复用子管道动态传递上下文。
    • 嗯,我能想到的最好的办法是通过将“传递上下文”嵌入到所有数据中来尽可能简单地完成它:play.golang.org/p/b-uXPuljyl。但这会导致到处都是非常尴尬的 .Content 前缀。由于模板似乎与外界完全隔离(可能是为了防止种族,正如你提到的),我不确定你是否真的可以简化它...
    【解决方案2】:

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

    但它有几个缺陷:

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

    【讨论】:

    • 可以通过在使用前克隆模板来解决线程安全问题。不过,这是有代价的。
    【解决方案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)})
    }
    

    【讨论】:

    • 我试图避免将 bool 放入管道中,因为正如您在其他地方所说的那样,很多事情很快就会“有点麻烦”编码。恕我直言,传递给模板的主管道应该是一个包含我们要渲染的实际数据的完整结构,但是其他典型的上下文数据应该是可用的,而不必在每个子模板的每个管道中复用它:当前语言和区域设置,用户配置文件, ACL。
    猜你喜欢
    • 2010-12-26
    • 1970-01-01
    • 2010-11-17
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2012-05-04
    • 2010-10-16
    相关资源
    最近更新 更多