google-app-engine - 访问 golang 模板中引用对象的属性(Google 应用引擎)

标签 google-app-engine templates go data-modeling google-cloud-datastore

我有一个数据模型Sections:

type Sections struct{
    SectionName     string
    IsFather        bool
    ParentSection   *datastore.Key
}

我将部分作为值传递给 golang 模板,我想获取 ParentSection 名称 ParentSection.SectionName 那么我如何从 jinja2 在 python {{ParentSection.get().SectionName}}?

最佳答案

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 来从 Datastore 加载实体,因此您也必须在模板参数中使其可用。所以你的模板参数可能看起来像这样:

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)

现在假设您有一个名为 "parSecName" 的父 Sections,并且您有一个名为 的子 Sections >“childSecName”,并且 child 的 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

如果您不想将父 key “存储”在实体的 key 本身中,那么只存储 key 的名称或 key 的 ID(取决于您使用的是什么)也可能就足够了,从那以后可以构造 key 。

关于google-app-engine - 访问 golang 模板中引用对象的属性(Google 应用引擎),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36384759/

相关文章:

c++ - 根据单独的模板化成员改变类的模板化成员函数的返回类型

go - 如何将exe文件作为窗口服务运行?

go - 在 HyperLedger Fabric 中对等节点安装链码

google-app-engine - 在哪里可以查看Google App Engine上托管Vms上部署失败的日志?

c++ - 模板是如何工作的,它们总是内联的吗?

具有 Cloud SQL 或数据存储的 Android App Engine

c++ - C++ 中的枚举映射

go - Sonarqube 是否支持 GO lang,如果不支持,那么该功能何时到位

java - 如何从 GAE servlet 发送 HTTPS 请求?

android - SHA1 指纹已被另一个 OAuth2 客户端使用