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

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

golang html/template templates with same names in different directories

问题

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

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

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

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

  1. type Handler struct {
  2. DB *sql.DB
  3. Tmpl *template.Template
  4. }

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

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

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

  1. templates\
  2. \agency
  3. --\edit.html
  4. --\index.html
  5. ... 用于agency的其他html文件
  6. \user
  7. --\edit.html
  8. --\index.html
  9. ... 用于用户的其他html文件
  10. ... 用于其他数据库对象的其他目录

我使用了以下代码:

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

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

  1. 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/)之后重新定义了相同名称的模板。

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

  1. 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:

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

where handlers is a struct with database pointer and templates,

  1. type Handler struct {
  2. DB *sql.DB
  3. Tmpl *template.Template
  4. }

and it's have a methods for catching responses:

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

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).

  1. templates\
  2. \agency
  3. --\edit.html
  4. --\index.html
  5. ... etc htmls for agency
  6. \user
  7. --\edit.html
  8. --\index.html
  9. ... etc htmls for users
  10. ... etc dirs for other DB-objects

And I'm using this:

  1. func main() {
  2. handlers := &amp;handler.Handler{
  3. DB: db,
  4. Tmpl: template.Must(template.ParseGlob(&quot;templates/*.html&quot;)), // for root templates
  5. }
  6. // next code is avoid panic: read templates/agency: is a directory
  7. template.Must(handlers.Tmpl.ParseGlob(&quot;templates/user/*.html&quot;))
  8. template.Must(handlers.Tmpl.ParseGlob(&quot;templates/agency/*.html&quot;))
  9. r := mux.NewRouter()
  10. r.HandleFunc(&quot;/&quot;, handlers.Index).Methods(&quot;GET&quot;) // root
  11. r.HandleFunc(&quot;/user&quot;, handlers.UserList).Methods(&quot;GET&quot;)
  12. r.HandleFunc(&quot;/agency&quot;, handlers.AgencyList).Methods(&quot;GET&quot;)
  13. // etc code with ListenAndServe()
  14. }

After all I catched error in template like

  1. 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:

  1. 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,在顶部添加以下行:

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

在底部添加以下行:

  1. {{ end }}

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

  1. 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

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

and this line at the bottom

  1. {{ end }}

and then the following

  1. 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:

确定