web-dev-qa-db-fra.com

GO: Comment rendre plusieurs modèles dans Golang?

Un modèle de base est créé . Avec ce rendu en premier.html, un autre modèle.

eg. :
    var tmpl = template.Must(template.ParseFiles(
    "templates/base.html",
    "templates/first.html",
    ))

Mais je veux aussi ajouter plus de fichiers .html à rendre . Une référence?

25
fmt.Fprint

Si vous définissez tous vos modèles dans un dossier de modèles, vous pouvez facilement analyser tout le répertoire avec:

template.Must(template.ParseGlob("YOURDIRECTORY/*"))

Par exemple:

head.html

{{define "header"}}
     <head>
         <title>Index</title>
     </head>
{{end}}

index.html

{{define "indexPage"}}
    <html>
    {{template "header"}}
    <body>
        <h1>Index</h1>
    </body>
    </html>
{{end}}

main.go

package main

import(
    "html/template"
)

// compile all templates and cache them
var templates = template.Must(template.ParseGlob("YOURTEMPLATEDIR/*"))

func main(){
    ...
}

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

    // you access the cached templates with the defined name, not the filename
    err := templates.ExecuteTemplate(w, "indexPage", nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

Vous exécutez votre template indexPage avec templates.ExecuteTemplate(w, "indexPage", nil)

78
ioboi

Vous pouvez facilement ajouter plus de fichiers .html en les ajoutant simplement comme arguments:

var tmpl = template.Must(template.ParseFiles(
    "templates/base.html",
    "templates/first.html",
    "templates/second.html",
))

Cela fonctionne bien tant que les premier et second ne définissent pas le même modèle.
Cependant, le package de modèles n'autorise pas l'appel dynamique de modèles, en utilisant une valeur de pipeline pour le nom du modèle. Donc, si vous essayez de faire quelque chose de similaire à mon exemple ci-dessous, cela ne fonctionnera pas.

Certaines solutions de contournement existent et il en est question sur Go-nut . Mais il semble que le package de modèle ait été conçu pour que vous ayez un objet *Template par page.

Exemple cassé de tentative d'appel de modèle dynamique:
Erreur: ".Content" inattendu dans l'appel du modèle

package main

import (
    "log"
    "os"
    "text/template"
)

const base= `<!DOCTYPE html>
<html>
    <head><title>Title</title></head>
<body>
    {{template .Content}}
</body>
</html>`

const first = `{{define "first"}}This is the first page{{end}}`
const second = `{{define "second"}}And here is the second{{end}}`

type View struct {
    Content  string
}

func main() {
    var view = &View{ "first" } // Here we try to set which page to view as content
    t := template.Must(template.New("base").Parse(base))
    t = template.Must(t.Parse(first))
    t = template.Must(t.Parse(second))
    err := t.Execute(os.Stdout, view)
    if err != nil {
        log.Println("executing template:", err)
    }
}

Code sur play.golang.org

7
ANisus

la partie 3 de ce tutoriel est utile:

http://golangtutorials.blogspot.co.nz/2011/11/go-templates-part-3-template-sets.html

Exemple du tutoriel:

Fichier de modèle complet - t1.tmpl

{{define "t_ab"}}a b{{template "t_cd"}}e f {{end}}

Le fichier ci-dessus sera analysé comme un modèle nommé "t_ab". Il contient "a b/missing/e f", mais il manque quelques lettres dans l'alphabet. Pour cela, il a l'intention d'inclure un autre modèle appelé "t_cd" (qui devrait être dans le même ensemble).

Fichier de modèle complet - t2.tmpl

{{define "t_cd"}} c d {{end}}

Le fichier ci-dessus sera analysé comme un modèle appelé "t_cd".

Programme complet

package main

import (
    "text/template"
    "os"
    "fmt"
    )

func main() {
    fmt.Println("Load a set of templates with {{define}} clauses and execute:")
    s1, _ := template.ParseFiles("t1.tmpl", "t2.tmpl") //create a set of templates from many files.
    //Note that t1.tmpl is the file with contents "{{define "t_ab"}}a b{{template "t_cd"}}e f {{end}}"
    //Note that t2.tmpl is the file with contents "{{define "t_cd"}} c d {{end}}"


    s1.ExecuteTemplate(os.Stdout, "t_cd", nil) //just printing of c d
    fmt.Println()
    s1.ExecuteTemplate(os.Stdout, "t_ab", nil) //execute t_ab which will include t_cd
    fmt.Println()
    s1.Execute(os.Stdout, nil) //since templates in this data structure are named, there is no default template and so it prints nothing
}
1
robert king

Si vous souhaitez analyser plusieurs répertoires avec des fichiers spécifiques, voici un extrait de code:

//parse a pattern in a specific directory  
allTemplates := template.Must(template.ParseGlob("Directory/*"))

//add another directory for parsing 
allTemplates = template.Must(allTemplates.ParseGlob("Another_Directory/*.tmpl"))

//add specific file name 
allTemplates = template.Must(allTemplates.ParseFiles("path/to/file.tmpl"))


func main() {
 ...
}

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

    // access cached template by file name (in case you didn't define its name) 
    err := allTemplates.ExecuteTemplate(w, "file.tmpl", nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

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

    // access cached template by handler name 
    err := allTemplates.ExecuteTemplate(w, "handlerName", nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

un raccourci rapide:

allTemplates := template.Must(
        template.Must(
        template.Must(
            template.ParseGlob("directory/*.tmpl")).
            ParseGlob("another_directory/*.tmpl")).
            ParseFiles("path/to/file.tmpl")),
                )

file.tmpl peut ressembler à ceci: 

<html>
This is a template file 
</html>

name.tmpl devrait ressembler à ceci

{{define "handlerName" }}
<p>this is a handler</p>
{{end}}
0
msoliman