How to pass data to template automatically in Go?

huangapple go评论164阅读模式
英文:

How to pass data to template automatically in Go?

问题

现在我正在使用Gorilla context包在我的中间件和控制器中传递数据,但我想要的是直接将数据传递给我的Pongo2模板,这样我在控制器中就不必从Gorilla context中获取数据并手动传递给模板上下文。对于熟悉express.js的人来说,就像这样:

  1. var user = {
  2. name: "Name",
  3. age: 0
  4. }
  5. response.locals = user

编辑:所以每个pongo2模板都需要访问一个User对象,现在我使用中间件从数据库中获取用户,并使用Gorilla context将数据传递给我的控制器,然后传递给每个控制器上的模板,但我想要的是在中间件中将User对象传递给模板,而不是使用Gorilla context。

  1. func UserMiddleware(next http.HandlerFunc) http.HandlerFunc {
  2. return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
  3. user := &User{} // user通常从数据库中获取
  4. context.Set(req, "user", user)
  5. next.ServeHTTP(res, req)
  6. })
  7. }

然后在我的请求处理程序中:

  1. func Handler(res http.ResponseWriter, req *http.Request) {
  2. tpl, _ := pongo2.FromFile("view/template.html")
  3. user := context.Get(req, "user").(*User)
  4. data := pongo2.Context{
  5. "user": user,
  6. }
  7. out, _ := tpl.Execute(data)
  8. res.Write([]byte(out))
  9. }

对于所有的处理程序,我都必须像这样传递user给模板,但我想要的是从我的中间件中传递它,这样我就不必在每个处理程序中这样做。

英文:

Right now i am using Gorilla context package to pass data around in my middlewares & controllers, but what i want to do is pass the data directly to my Pongo2 template so later in my controller i don't have to get the data from the Gorilla context and manually pass it to the template context, for those of you familiar with express.js it would be like

  1. var user = {
  2. name: "Name",
  3. age: 0
  4. }
  5. response.locals = user

Edit: So every pongo2 template needs access to a User object, right now i fetch the user from database using middleware and using Gorilla context pass the data to my controller, from there on to my template on each controller but what i want to do is pass the User object to template from my middleware instead of using Gorilla context.

  1. func UserMiddleware(next http.HandlerFunc) http.HandlerFunc {
  2. return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
  3. user := &User{} // user will normally be fetched from database
  4. context.Set(req, "user", user)
  5. next.ServeHTTP(res, req)
  6. })
  7. }

Then In My Request Handler

  1. func Handler(res http.ResponseWriter, req *http.Request) {
  2. tpl, _ := pongo2.FromFile("view/template.html")
  3. user := context.Get(req, "user").(*User)
  4. data := pongo2.Context{
  5. "user": user,
  6. }
  7. out, _ := tpl.Execute(data)
  8. res.Write([]byte(out))
  9. }

For all of my handlers i have to pass in user to template like that, but i want to pass it in from my middleware so that i don't have to do it in each of my handlers.

答案1

得分: 1

请注意,以下是翻译好的内容:

使用MyExecute(req, tpl)来替代tpl.Execute(data)

  1. func MyExecute(req *http.Request, tpl TemplateSet) (string, error){
  2. gorillaObj := context.GetAll(req)
  3. pongoObj := make(map[string]interface{})
  4. for key, value := range gorillaObj {
  5. if str, ok := key.(string); ok{
  6. pongoObj[str] = value
  7. }
  8. }
  9. return tpl.Execute(pongo2.Context(pongoObj))
  10. }

未经测试,但应该可以工作。
最大的问题是gorilla使用map[interface{}]interface{}作为存储,而pongo使用map[string]interface{},请注意在gorilla上下文中不要使用非字符串作为键。

英文:

invoke MyExecute(req, tpl) instead of tpl.Execute(data)

  1. func MyExecute(req *http.Request, tpl TemplateSet) (string, error){
  2. gorillaObj := context.GetAll(req)
  3. pongoObj := make(map[string]interface{})
  4. for key, value := range gorillaObj {
  5. if str, ok := key.(string); ok{
  6. pongoObj[str] = value
  7. }
  8. }
  9. return tpl.Execute(pongo2.Context(pongoObj))
  10. }

not tested, it should work.
the most problem is that gorilla use map[interface{}]interface{} as store, but pongo use map[string]interface{}, note not to use non-string as key in gorilla context.

huangapple
  • 本文由 发表于 2015年9月10日 13:16:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/32493677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定