在不同目录中具有相同名称的golang html/template模板

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

golang html/template templates with same names in different directories

问题

问题:
如果不同文件夹中的方法(具有不同路由)需要指定特定的模板,该如何操作?

描述:
我在数据库中有两个表,Users和Agency,它们具有不同的字段。对于每个表,我都使用SELECT函数创建了一个用于列出对象的路由。
路由器:

r := mux.NewRouter() // gorilla/mux
r.HandleFunc("/user", handlers.UserList).Methods("GET")
r.HandleFunc("/agency", handlers.AgencyList).Methods("GET")

其中handlers是一个带有数据库指针和模板的结构体,

type Handler struct {
    DB   *sql.DB
    Tmpl *template.Template
}

它具有用于捕获响应的方法:

func (h *Handler) AgencyList(w http.ResponseWriter, r *http.Request) {
    Agencys := []*Agency{}
    rows, err := h.DB.Query(`SELECT Id, Name, IsActive FROM Agencys`)
    // 将对象追加到Agencys中并处理错误的代码等
    err = h.Tmpl.ExecuteTemplate(w, "index.html", struct{ Agencys []*Agency }{Agencys: Agencys})
    // 其他代码和错误处理
}

处理Users列表函数的原则相同。
此处理程序还具有用于GET(一个对象)、POST和DELETE方法的方法,对于每个方法,我都需要特定的模板(用于编辑等)。
所以。
在这个例子中,我有一个名为templates的目录,其中有两个子目录"user"和"agency",每个"subject"(用户和机构)都有一个用于列出对象的index.html文件。

templates\
  \agency
   --\edit.html
   --\index.html
   ... 用于agency的其他html文件
  \user
   --\edit.html
   --\index.html
   ... 用于用户的其他html文件
  ... 用于其他数据库对象的其他目录

我使用了以下代码:

func main() {
    handlers := &handler.Handler{
        DB:   db,
        Tmpl: template.Must(template.ParseGlob("templates/*.html")), // 用于根模板
    }
    // 下面的代码是为了避免出现panic: read templates/agency: is a directory
    template.Must(handlers.Tmpl.ParseGlob("templates/user/*.html"))
    template.Must(handlers.Tmpl.ParseGlob("templates/agency/*.html"))
    r := mux.NewRouter()
    r.HandleFunc("/", handlers.Index).Methods("GET") // 根目录
    r.HandleFunc("/user", handlers.UserList).Methods("GET")
    r.HandleFunc("/agency", handlers.AgencyList).Methods("GET")
    // 其他使用ListenAndServe()的代码
}

最后,我在模板中捕获了错误,例如:

template: index.html:26:12: executing "index.html" at <.Agencys>: can't evaluate field Agencys in type struct { Users []*handler.User }

当我尝试在浏览器中调用localhost/user进行列表时(因为它们是不同的“对象”,具有不同的字段,当然会出错)。看起来像是ParseGlob(agency/)在ParseGlob(user/)之后重新定义了相同名称的模板。

我尝试找到解决方案,例如:

err = h.Tmpl.ExecuteTemplate(w, "templates/user/index.html", post)

在UserList()方法中指定需要的模板。

也许这不是一个好的解决方案;也许,如果我在模板名称中使用前缀(例如在templates目录中使用listAgency.html和listUser.html)而不是为每个对象使用不同的目录,那可能会更好。我尝试过这种方式,但看起来不太美观。

英文:

Question:
How can I specify a specific template for a specific method (with different routes), if they are in different folders and named the same?

Descript:

I have two tables in Database, Users and Agency with different fields for example. For each of them I've made router for list objects by SELECT function.
Router:

r := mux.NewRouter() // gorilla/mux
r.HandleFunc(&quot;/user&quot;, handlers.UserList).Methods(&quot;GET&quot;)
r.HandleFunc(&quot;/agency&quot;, handlers.AgencyList).Methods(&quot;GET&quot;)

where handlers is a struct with database pointer and templates,

type Handler struct {
    DB   *sql.DB
    Tmpl *template.Template
}

and it's have a methods for catching responses:

func (h *Handler) AgencyList(w http.ResponseWriter, r *http.Request) {
	Agencys := []*Agency{}
	rows, err := h.DB.Query(`SELECT Id, Name, IsActive FROM Agencys`)
	// etc code for append objects into Agencys and error handling
	err = h.Tmpl.ExecuteTemplate(w, &quot;index.html&quot;, struct{ Agencys []*Agency }{Agencys: Agencys})
	// etc code and error handling
}

Same principles in handling Users list function.
This handler have also methods for GET (one object) POST and DELETE methods, and for each of them I need specific template for working (for editing etc).
So.
In this example I have directory templates, where I have two sub-directories "user" and "agency" with files index.html (for listing objects) for each "subject" (user and agency).

templates\
  \agency
   --\edit.html
   --\index.html
   ... etc htmls for agency
  \user
   --\edit.html
   --\index.html
   ... etc htmls for users
  ... etc dirs for other DB-objects

And I'm using this:

func main() {
	handlers := &amp;handler.Handler{
		DB:   db,
		Tmpl: template.Must(template.ParseGlob(&quot;templates/*.html&quot;)), // for root templates
	}
	// next code is avoid panic: read templates/agency: is a directory
	template.Must(handlers.Tmpl.ParseGlob(&quot;templates/user/*.html&quot;))
	template.Must(handlers.Tmpl.ParseGlob(&quot;templates/agency/*.html&quot;))
	r := mux.NewRouter()
	r.HandleFunc(&quot;/&quot;, handlers.Index).Methods(&quot;GET&quot;) // root
	r.HandleFunc(&quot;/user&quot;, handlers.UserList).Methods(&quot;GET&quot;)
	r.HandleFunc(&quot;/agency&quot;, handlers.AgencyList).Methods(&quot;GET&quot;)
// etc code with ListenAndServe()
}

After all I catched error in template like

template: index.html:26:12: executing &quot;index.html&quot; at &lt;.Agencys&gt;: can&#39;t evaluate field Agencys in type struct { Users []*handler.User } 

when I trying call localhost/user listing in browser (because it's different 'objects' with different fields, of course). Looks like ParseGlob(agency/) redefine tepmlates with same names after ParseGlob(user/)

I'm trying find solution like this:

err = h.Tmpl.ExecuteTemplate(w, &quot;templates/user/index.html&quot;, post)

in method UserList() for pointing which template needs.

Maybe that's all is not good solution; maybe will be good, if I shall use prefixes in template's names (like listAgency.html and listUser.html in templates dir) instead of different directories for each object like now. I tried this way, but that looks not so pretty and beauty.

答案1

得分: 1

你可以像这样包装每个文件的内容,并给它起一个你想要的名字。

例如,打开文件 templates\user\index.html,在顶部添加以下行:

{{ define "templates/user/index.html" }}

在底部添加以下行:

{{ end }}

然后,下面的代码就可以正常工作了:

err = h.Tmpl.ExecuteTemplate(w, "templates/user/index.html", post)
英文:

> I'm trying find solution like this:
> go
&gt; err = h.Tmpl.ExecuteTemplate(w, &quot;templates/user/index.html&quot;, post)
&gt;

You can wrap each file's contents in a "define action" and name it what you want.

For example, open the file templates\user\index.html and add a this line at the top

{{ define &quot;templates/user/index.html&quot; }}

and this line at the bottom

{{ end }}

and then the following

err = h.Tmpl.ExecuteTemplate(w, &quot;templates/user/index.html&quot;, post)

will work.

huangapple
  • 本文由 发表于 2021年12月1日 02:26:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/70174318.html
匿名

发表评论

匿名网友

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

确定