【问题标题】:Cannot bind mysql data to html template in golang无法将mysql数据绑定到golang中的html模板
【发布时间】:2022-01-16 01:26:48
【问题描述】:

更新:任何地方都没有错误!在浏览器中,控制台或网络选项卡中没有错误。在运行 go 代码的终端中,也没有错误。 go中的所有错误都会被记录;为简洁起见,我删除了问题中的错误处理。

正在尝试阅读一本关于使用 Go 编写 Web 应用程序的书。 我有一个本地 mysql 数据库,我可以使用 database/sql 包获取数据。我正在使用html/template 包解析模板,但不知何故无法将数据绑定到模板中。

这是模型:

type Snippet struct {
    ID      int
    Title   string
    Content string
    Created time.Time
    Expires time.Time
}

这是用于显示数据的handler(省略了错误处理):

func (app *application) showSnippet(w http.ResponseWriter, r *http.Request) {
    id, _ := strconv.Atoi(r.URL.Query().Get("id"))
    s, _ := app.snippets.Get(id) // get data from database!
    files := []string{
        "./ui/html/show.page.tmpl", // this is the template.
        "./ui/html/base.layout.tmpl",
        "./ui/html/footer.partial.tmpl", // either relative or absolute path!
    }
    ts, _ := template.ParseFiles(files...)
    _ = ts.Execute(w, s) // write the template set content as the response body; 
    
    // NOTE: this does print out data fine so data is indeed retrieved from the db.
    fmt.Fprintf(w, "%s\n%s", s.Title, s.Content) 
}

这是show.page.tmpl 模板:

{{template "base" .}}
{{define "title"}}Snippet #{{.ID}}{{end}}
{{define "main"}}
<div class='snippet'>
    <div class='metadata'>
        <strong>{{.Title}}</strong>
        <span>#{{.ID}}</span>
    </div>
    <pre><code>{{.Content}}</code></pre>
    <div class='metadata'>
        <time>Created: {{.Created}}</time>
        <time>Expires: {{.Expires}}</time>
    </div>
</div>
{{end}}

在页面上,它不显示数据,因为它是空的;但调试行在底部打印得很好。 出了什么问题?

【问题讨论】:

  • @CeriseLimón 在问题中,为简洁起见省略了错误处理;实际上,来自ts.Execute(w, s) 的错误是使用集中式错误处理记录的。
  • @CeriseLimón 抱歉,但没有任何地方出现错误。在浏览器中,没有错误,在终端中,没有错误。我根本看不到任何错误。如您所见,调试消息打印在最后一行,如果在此之前有任何错误,它会显示在某个地方。
  • this example。该模板是独立工作的。发布minimal reproducible example

标签: mysql go


【解决方案1】:

在 HTTP 处理程序中编译模板不是一个好主意(基本上在每个请求中)

假设您使用模板名称和 .htm 扩展名创建了文件,您可以这样做(甚至将它们添加到应用程序结构中)

// Define a global templates variable (or add it to the application if you want)
var templates *template.Template
// For compiling the templates
// in a subdirectory called "templates" with files ending in .htm
func getTemplates() (templates *template.Template, err error) {
    var allFiles []string
    templateDir := "templates"
    files2, _ := ioutil.ReadDir(templateDir)
    for _, file := range files2 {
        filename := file.Name()
        if strings.HasSuffix(filename, ".htm") {
            filePath := filepath.Join(templateDir, filename)
            allFiles = append(allFiles, filePath)
        }
    }
    templates, err = template.New("").ParseFiles(allFiles...)
    LogPanic(err, "Error building templates")
    return
}
// load them on init
func init() {
    var err error
    templates, err = getTemplates()
    if err != nil {
        log.Panicf("%s: %s \n", "ERROR compiling templates", err)
    }
}

现在您已经编译了模板,您可以在 HTTP 处理程序中执行它们,如果有任何错误,请记录错误(如果您看到 Cerise Limón 建议的任何错误,请分享)记得更新代码中的模板名称。

func (app *application) showSnippet(w http.ResponseWriter, r *http.Request) {
    id, _ := strconv.Atoi(r.URL.Query().Get("id"))
    s, _ := app.snippets.Get(id)
    err := templates.ExecuteTemplate(w, "template_name", s)
    if err != nil {
        log.Printf("%s: %s \n", "ERROR executing template", err)
    }
    fmt.Fprintf(w, "%s\n%s", s.Title, s.Content) 
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    • 2020-05-28
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多