我有一个数据模型Sections:
type Sections struct{
SectionName string
IsFather bool
ParentSection *datastore.Key
}我将部分作为值传递给golang模板,并且我希望获得ParentSection名称ParentSection.SectionName,所以如何从python{{ParentSection.get().SectionName}}中的jinja2这样的模板中实现这一点?
发布于 2016-04-04 08:08:57
html/template包不具有“应用引擎感知”,它不了解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",还有一个名为"childSecName"的子Sections,子ParentSection指向父Sections的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 (取决于您使用的内容),因为可以构造密钥。
https://stackoverflow.com/questions/36384759
复制相似问题