0

html/templateGoを使用してテンプレートを埋め込むことに頭を悩ませようとしています。私はロジックのないテンプレートのデザインがとても好きで、期待通りに安全にエスケープする能力に自信を持っています (他のテンプレート ライブラリがこれを間違えることがあります)。

ただし、「最終的な」テンプレート名に基づいて HTTP ハンドラーでテンプレートをレンダリングするための小さなヘルパーを実装しようとすると、少し問題が発生します。私の base.tmpl は、すべてのページで事実上「標準」であり、そうでない場合は{{ template checkoutJS }}、base.tmpl に設定し、設定することでページごとの JS を追加できます{{ define checkoutJS }}https://path.to/extra.js {{ end }}

renderTemplate(w, "template_name.tmpl", data)HTTP ハンドラーで、data入力したいものを含む文字列または構造体を含む map[string]interface{} はどこにあると言えるようにしたいと考えています。

これまでのコードは次のとおりです。

base.tmpl

{{ define "base" }}
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ template "title" . }}</title>
</head>
<body>
<div id="sidebar">
...
</div>

{{ template "content" }}

<div id="footer">
...
</div>
</body>
</html>

create_listing.tmpl

{{ define "title" }}Create a New Listing{{ end }}

{{ define "content" }}

<form>
  ...
</form>

{{ end }}

login_form.tmpl

{{ define "title" }}Login{{ end }}

{{ define "content" }}

<form>
  ...
</form>

{{ end }}

main.go

package main

import (
  "fmt"
    "github.com/gorilla/mux"
    "html/template"
    "log"
    "net/http"
)

// Template handling shortcuts
var t = template.New("base")

func renderTemplate(w http.ResponseWriter, tmpl string, data map[string]interface{}) {

    err := t.ExecuteTemplate(w, tmpl, data)

  // Things will be more elegant than this: just a placeholder for now!
    if err != nil {
        http.Error(w, "error 500:"+" "+err.Error(), http.StatusInternalServerError)
    }
}

func monitorLoginForm(w http.ResponseWriter, r *http.Request) {

    // Capture forms, etc.

    renderTemplate(w, "login_form.tmpl", nil)
}

func createListingForm(w http.ResponseWriter, r *http.Request) {

    // Grab session, re-populate form if need be, generate CSRF token, etc

    renderTemplate(w, "create_listing.tmpl", nil)
}

func main() {

    r := mux.NewRouter()

    r.HandleFunc("/monitor/login", monitorLoginForm)

    http.Handle("/", r)
    log.Fatal(http.ListenAndServe(":8000", nil))

}

func init() {

    fmt.Println("Starting up.")
    _, err := t.ParseGlob("templates/*.tmpl")
    if err != nil {
        log.Fatal("Error loading templates:" + err.Error())
    }
}

これはコンパイルされますが、ハンドラーから空の応答が返されます。2 番目のハンドラーのルートがないことに注意してください。このコードはrenderTemplate()、ハンドラーからどのように呼び出したいかを示すためのものです。

4

2 に答える 2

2

現在の go テンプレート パッケージでは、やりたいことができません。テンプレートには継承がないため、テンプレートにあるような名前付きブロックはありません。ベース テンプレートを定義する代わりに、ヘッダー テンプレートとフッター テンプレートを定義する方が一般的です。次に、ページ テンプレートで、配置したい場所にそれらを明示的に含めます。

もう 1 つの解決策は、2 段階のテンプレート フェーズを用意することだと思います。1 つ目は、基本テンプレートのすべてのブロックのテンプレートをコンパイルすることです。これらはマップに追加され、ベース テンプレートに送信されて含められます。

于 2013-10-15T05:50:06.093 に答える
1

これはかなり自明ではなく、なぜ彼らがこのようにするのかわかりません

ParseGlob は、破棄している値を返しますが、それを保持する必要があります。呼び出す必要があるのはテンプレート オブジェクトなので、コードは次のようになります。

func init() {
  fmt.Println("Starting up.")
  t, err := template.ParseGlob("templates/*.tmpl")
  if err != nil {
    log.Fatal("Error loading templates:" + err.Error())
  }
}

メソッドのドキュメント (上記で使用されたライブラリ関数とは対照的に) は、メソッドが呼び出されたテンプレート オブジェクトにテンプレートを関連付けると述べているため、少し不明確ですが、テンプレート オブジェクトへのポインターも返します。宣伝どおりに機能する場合は、これを行う必要はありません。楽しい!

于 2013-10-15T05:57:21.663 に答える