【问题标题】:access properties of referenced objects in golang template (Google app engine)访问golang模板中引用对象的属性(谷歌应用引擎)
【发布时间】:2016-07-22 22:31:19
【问题描述】:

我有一个数据模型Sections:

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

我将部分作为值传递给 golang 模板,并且我想获取 ParentSection 名称 ParentSection.SectionName 那么如何从 python {{ParentSection.get().SectionName}} 中的 jinja2 之类的模板执行此操作?

【问题讨论】:

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


    【解决方案1】:

    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)
    

    现在假设您有一个名为 "parSecName" 的父 Sections,您有一个名为 "childSecName" 的子 Sections,并且子的 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(取决于您使用的内容)也可能就足够了,因为可以构造密钥。

    【讨论】:

      猜你喜欢
      • 2016-12-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 2013-02-26
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多