我有一个数据模型Sections:
type Sections struct{
SectionName string
IsFather bool
ParentSection *datastore.Key
}
我将部分作为值传递给golang模板,我希望得到ParentSection
名称ParentSection.SectionName
,那么如何从python jinja2
中的{{ParentSection.get().SectionName}}
等模板执行此操作?< / p>
答案 0 :(得分:0)
html/template
包不是“appengine-aware”,它不了解GAE平台,也不支持自动解决此类引用。
根据设计理念,模板不应包含复杂的逻辑。如果某些内容(或看起来)在模板中过于复杂,则应在函数中实现。您可以使用Template.Funcs()
方法注册自定义函数,您可以从模板中调用它。
对于您的用例,我建议使用以下自定义函数,该函数通过其键加载Sections
:
func loadSections(ctx appengine.Context, k *datastore.Key) (*Sections, error) {
s := Sections{}
err := datastore.Get(ctx, k, &s)
return &s, err
}
请注意,您需要Context
来加载数据存储区中的实体,因此您必须在模板参数中使其可用。所以你的模板参数可能如下所示:
ctx := appengine.NewContext(r)
m := map[string]interface{}{
"Sections": s, // A previously loaded Sections
"Ctx": ctx,
}
通过注册和使用此功能,您可以获得所需内容:
t := template.Must(template.New("").Funcs(template.FuncMap{
"loadSections": loadSections,
}).Parse(`my section name: {{.Sections.SectionName}},
parent section name: {{(loadSections .Ctx .Sections.ParentSection).SectionName}}`))
t.Execute(w, m)
现在假设您有一个名为Sections
的父"parSecName"
,您的孩子Sections
的名称为"childSecName"
,而孩子的ParentSection
指向父母的Sections
。执行上述模板,您将看到以下结果:
my section name: childSecName,
parent section name: parSecName
请参阅此完整的工作示例。注意:它仅用于演示目的,未针对生产进行优化。
它注册/put
路径以插入2 Sections
。您可以使用任何其他路径来执行模板。所以测试它是这样的:
首先插入2 Sections
:
http://localhost:8080/put
然后执行并查看模板结果:
http://localhost:8080/view
完成可运行代码:
// +build appengine
package gplay
import (
"appengine"
"appengine/datastore"
"html/template"
"net/http"
)
func init() {
http.HandleFunc("/put", puthandler)
http.HandleFunc("/", myhandler)
}
func myhandler(w http.ResponseWriter, r *http.Request) {
ctx := appengine.NewContext(r)
s := Sections{}
if err := datastore.Get(ctx, datastore.NewKey(ctx, "Sections", "", 2, nil), &s); err != nil {
panic(err)
}
m := map[string]interface{}{
"Sections": s,
"Ctx": ctx,
}
t := template.Must(template.New("").Funcs(template.FuncMap{
"loadSections": loadSections,
}).Parse(`my section name: {{.Sections.SectionName}},
parent section name: {{(loadSections .Ctx .Sections.ParentSection).SectionName}}`))
t.Execute(w, m)
}
func loadSections(ctx appengine.Context, k *datastore.Key) (*Sections, error) {
s := Sections{}
err := datastore.Get(ctx, k, &s)
return &s, err
}
func puthandler(w http.ResponseWriter, r *http.Request) {
ctx := appengine.NewContext(r)
s := Sections{"parSecName", false, nil}
var k *datastore.Key
var err error
if k, err = datastore.Put(ctx, datastore.NewKey(ctx, "Sections", "", 1, nil), &s); err != nil {
panic(err)
}
s.SectionName = "childSecName"
s.ParentSection = k
if _, err = datastore.Put(ctx, datastore.NewKey(ctx, "Sections", "", 2, nil), &s); err != nil {
panic(err)
}
}
type Sections struct {
SectionName string
IsFather bool
ParentSection *datastore.Key
}
此子父母关系可以使用Key
本身建模,因为键可以选择包含父Key
。
如果您不想在实体的密钥本身中“存储”父密钥,也可以只存储密钥的名称或密钥的ID(取决于您使用的内容),因为密钥可以构建。