首页 > 其他分享 >03-template-advance

03-template-advance

时间:2024-04-07 10:45:17浏览次数:24  
标签:templates 03 err advance content html User template

03-Template Advance

源作者地址:https://github.com/bonfy/go-mega 仅个人学习使用
学习完 第二章 之后,你对模板已经有了基本的认识

本章将讨论 Go 的组合特性,以及 建立一个通用的调用 模板的方法

本章的GitHub链接为: Source, Diff,
Zip

匿名组合

匿名组合 其实是Go里的一个非常重要的特性,在 Go 的世界里没有继承,只有组合(当然还有接口)。组合其实可以实现部分的继承。

main.go

type Post struct {
    User
    Body string
}

// IndexViewModel struct
type IndexViewModel struct {
    Title string
    User
    Posts []Post
}

就是 将 User User -> User其它都不变,这样执行,发现程序照常运行

不过,现在我们可以改下templates/index.html

templates.index.html

<html>
    <head>
        {{if .Title}}
            <title>{{.Title}} - blog</title>
        {{else}}
            <title>Welcome to blog!</title>
        {{end}}
    </head>
    <body>
        <h1>Hello, {{.Username}}!</h1>
        {{range .Posts}}
            <div><p>{{ .Username }} says: <b>{{ .Body }}</b></p></div>
        {{end}}

    </body>
</html>

由于 匿名组合 ,我们现在可以将 {{.User.Username}} -> {{.Username}}

就是我们可以直接使用 匿名组合 的属性,以及方法,其实也是变像的实现了继承。

关于 Go 的 面向对象,可以看下 参考

本小节 Diff

模板继承

其实 Go 的模板应该没有 Flask jinja2 这样的功能强大,它只有 include,所以为了实现模板的继承,我们需要发挥下主观能动性

main.go

package main

import (
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
)

// User struct
type User struct {
	Username string
}

// Post struct
type Post struct {
	User
	Body string
}

// IndexViewModel struct
type IndexViewModel struct {
	Title string
	User
	Posts []Post
}

// PopulateTemplates func
// Create map template name to template.Template
func PopulateTemplates() map[string]*template.Template {
	const basePath = "templates"
	result := make(map[string]*template.Template)

	layout := template.Must(template.ParseFiles(basePath + "/_base.html"))
	dir, err := os.Open(basePath + "/content")
	if err != nil {
		panic("Failed to open template blocks directory: " + err.Error())
	}
	fis, err := dir.Readdir(-1)
	if err != nil {
		panic("Failed to read contents of content directory: " + err.Error())
	}
	for _, fi := range fis {
		func() {
			f, err := os.Open(basePath + "/content/" + fi.Name())
			if err != nil {
				panic("Failed to open template '" + fi.Name() + "'")
			}
			defer f.Close()
			content, err := ioutil.ReadAll(f)
			if err != nil {
				panic("Failed to read content from file '" + fi.Name() + "'")
			}
			tmpl := template.Must(layout.Clone())
			_, err = tmpl.Parse(string(content))
			if err != nil {
				panic("Failed to parse contents of '" + fi.Name() + "' as template")
			}
			result[fi.Name()] = tmpl
		}()
	}
	return result
}

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		u1 := User{Username: "bonfy"}
		u2 := User{Username: "rene"}

		posts := []Post{
			Post{User: u1, Body: "Beautiful day in Portland!"},
			Post{User: u2, Body: "The Avengers movie was so cool!"},
		}

		v := IndexViewModel{Title: "Homepage", User: u1, Posts: posts}

		templates := PopulateTemplates()
		templates["index.html"].Execute(w, &v)
	})
	http.ListenAndServe(":8888", nil)
}

templates/_base.html

<html>
    <head>
        {{if .Title}}
        <title>{{.Title}} - blog</title>
        {{else}}
        <title>Welcome to blog!</title>
        {{end}}
    </head>
    <body>
        <div>Blog: <a href="/">Home</a></div>
        {{template "content" .}}
    </body>
</html>

templates/content/index.html

{{define "content"}}
    <h1>Hello, {{.User.Username}}!</h1>

    {{range .Posts}}
        <div><p>{{ .User.Username }} says: <b>{{ .Body }}</b></p></div>
    {{end}}
{{end}}

这里用了模板继承,_base 是 基础模板,这样 比如 head 等信息不用再重复的去在每个.html文件中重复定义,我们可以专注于每个页面的业务逻辑和内容。

由于没有像 Jinja2 这样的原生支持模板继承,这个实现的关键就是 PopulateTemplates 函数,它的作用是 遍历 templates/content/ 文件夹下的所有文件,并和 templates/_base.html 合成 template.Template,然后再存入 map 中(在 Python 中一般叫 dict),可以使用例如 index.html 的 key 来访问。

我们现在运行下程序,页面还是和原来一样(只是我们在 _base template 里面加入了 Home 的导航),不过我们的templates文件夹已经有了基础模板,并且具备了快速扩展的能力。下章 Web Form 我们可以看见效果。

03-01

本小节 Diff

标签:templates,03,err,advance,content,html,User,template
From: https://www.cnblogs.com/Edward6/p/18118561

相关文章

  • 02-template-basic
    02-TemplateBasic源作者地址:https://github.com/bonfy/go-mega仅个人学习使用学习完第一章之后,我们已经拥有了虽然一个简单,但可以成功运行Web应用本章将沿用这个应用,在此之上,加入模版渲染,使得页面更丰富本章的GitHub链接为:Source,Diff,Zip什么是模板微博应用程序的......
  • 记录一下远程链接mysql报host 'xxx.xxx.xxx' is not allowed to connect to this mysq
    问题说明:服务器上的mysql本地是可以链接3306端口的,但是远程链接服务器的3306端口报错,在排除了 服务器端口和服务器防火墙 的问题之后,确定问题应该是mysql的问题解决方式:1.点击mysql命令 2.输入数据库密码 3.输入 usemysql4.输入  updateusersethost=......
  • C++设计模式:TemplateMethod模式(一)
    1、概念定义定义一个操作中的算法的骨架结构(稳定),而将一些步骤延迟(变化)到子类中。TemplateMethod使得子类可以不改变(复用)一个算法的骨架结构即可重定义(override重写)该算法的某些特定步骤在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但是各个子步骤却有很......
  • C语言03-数据类型、运算符
    第6章数据类型6.5获取数据存储大小sizeof 运算符,可以计算出指定数据的字节大小结果是size_t类型的数据,对应的格式占位符是%zu使用说明:计算指定数据的字节大小1、sizeof和数据类型名称一起使用eg:printf("char:%zu\n",sizeof(char));2、sizeof和变量......
  • 后端学习记录~~JavaSE篇(day03-流程控制语句-上)
    if...else与Switch...case语句一、表达式和语句表达式:(1)变量或常量+运算符构成的计算表达式(2)new表达式,结果是一个数组或类的对象。(3)方法调用表达式,结果是方法返回值或void(无返回值)。语句:(1)分支语句:if...else,switch...case(2)循环语句:for,while,do...while(3)跳转语句:brea......
  • P2036 [COCI2008-2009 #2] PERKET
    题目描述Perket是一种流行的美食。为了做好Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种......
  • SciTech-Mathmatics-Advanced Algebra-LinearAlgebra: 矩阵的相抵、相似与合同
    https://www.math.pku.edu.cn/teachers/baozq/algebra/alg1.htm矩阵的相抵、相似与合同基本概念:相抵,相抵标准形相似,对角化,迹,可对角化矩阵的相似标准形特征值,特征向量,特征多项式,特征子空间正交矩阵,Kn的内积,标准正交基实对称矩阵的正交相似标准形二次型......
  • CF30D King's Problem? 题解
    CF30D题意有\(n+1\)个点,其中的\(n\)个点在数轴上。求以点\(k\)为起点走过所有点的最短距离,允许重复。思路有两种情况:\(k\)在数轴上(如图1)。\(k\)在第\(n+1\)个点上(如图2)。图1:图2:像第一种情况:一定存在数轴上某点\(k\),使得人先走遍\(1\simk\),回来,再走遍......
  • 16天【代码随想录算法训练营34期】第六章 二叉树part03(● 104.二叉树的最大深度 559
    104.二叉树的最大深度#Definitionforabinarytreenode.#classTreeNode:#def__init__(self,val=0,left=None,right=None):#self.val=val#self.left=left#self.right=rightclassSolution:defmaxDepth(self,root:O......
  • CCF-CSP认证202403个人总结以及部分代码
    第一次参加,总分340,这个成绩个人觉得比较满意了,毕竟考前一直在划水,也很久没写算法题了。写到第四题,觉得还剩一个小时肯定写不完就又开始划水,暴力模拟完了就开始翻网页抄自己的提交记录,无所事事,想提前交卷。考试结束在网上一搜,第四题好像不是很难,瞬间觉得没写到最后亏了,开始后悔。......