英文:
Execute multiple templates conditionally
问题
我有一个包含两个视图的网页,一个是匿名用户视图,另一个是管理员用户视图。我想要只为管理员用户显示一个导航栏,其他内容对于两种用户类型都保持不变。
这是我目前尝试过的代码:
main.go
package main
import (
"log"
"net/http"
"text/template"
"github.com/julienschmidt/httprouter"
)
func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// 获取基本身份验证凭据
user, password, hasAuth := r.BasicAuth()
if hasAuth && user == requiredUser && password == requiredPassword {
// 将请求委托给给定的处理函数
h(w, r, ps)
} else {
// 否则要求进行基本身份验证
w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
}
}
func Anonymous(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
t, err := template.ParseFiles("index.html")
if err != nil {
log.Fatalln(err)
}
err = t.Execute(w, map[string]string{"Name": "Anonymous"})
if err != nil {
log.Fatalln(err)
}
}
func Admin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
t, err := template.ParseFiles("index.html", "admin.html")
if err != nil {
log.Fatalln(err)
}
err = t.Execute(w, map[string]string{"Name": "Admin"})
if err != nil {
log.Fatalln(err)
}
}
func main() {
user := "admin"
pass := "1234"
router := httprouter.New()
router.GET("/", Anonymous)
router.GET("/admin/", BasicAuth(Admin, user, pass))
log.Fatal(http.ListenAndServe(":8080", router))
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ .Name }}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script>
function counter() {
document.getElementById("x").innerHTML = "x: " + document.querySelectorAll('.x').length;
document.getElementById("y").innerHTML = "y: " + document.querySelectorAll('.y').length;
document.getElementById("z").innerHTML = "z: " + document.querySelectorAll('.z').length;
}
</script>
</head>
<body onload="counter()">
{{ template "dashboard" }}
<nav class="navbar fixed-bottom">
<div class="container-fluid nav-justified">
<span id="x" class="navbar-brand nav-item"></span>
<span id="y" class="navbar-brand nav-item"></span>
<span id="z" class="navbar-brand nav-item"></span>
</div>
</nav>
</body>
</html>
admin.html
{{ define "dashboard" }}
<nav class="navbar">
<div class="container-fluid nav-justified">
<span class="nav-item">
<a class="navbar-brand" href="/a">a</a>
</span>
<span class="nav-item">
<a class="navbar-brand" href="/b">b</a>
</span>
<span class="nav-item">
<a class="navbar-brand" href="/c">c</a>
</span>
</div>
</nav>
{{ end }}
我的假设是,因为在为匿名用户执行模板时没有传入admin.html模板,所以dashboard模板不会被解析。然而,我遇到了这个错误:
template: index.html:18:14: executing "index.html" at <{{template "dashboard"}}>: template "dashboard" not defined
我该如何修复这个问题,或者有没有更好的方法来实现这个功能?
英文:
I have a webpage with two views, one for the anonymous user and one for the admin user. I want to display a navbar only for the admin user. Everything else remains the same for both the user types.
This is what I've tried so far
main.go
package main
import (
"log"
"net/http"
"text/template"
"github.com/julienschmidt/httprouter"
)
func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// Get the Basic Authentication credentials
user, password, hasAuth := r.BasicAuth()
if hasAuth && user == requiredUser && password == requiredPassword {
// Delegate request to the given handle
h(w, r, ps)
} else {
// Request Basic Authentication otherwise
w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
}
}
func Anonymous(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
t, err := template.ParseFiles("index.html")
if err != nil {
log.Fatalln(err)
}
err = t.Execute(w, map[string]string{"Name": "Anonymous"})
if err != nil {
log.Fatalln(err)
}
}
func Admin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
t, err := template.ParseFiles("index.html", "admin.html")
if err != nil {
log.Fatalln(err)
}
err = t.Execute(w, map[string]string{"Name": "Admin"})
if err != nil {
log.Fatalln(err)
}
}
func main() {
user := "admin"
pass := "1234"
router := httprouter.New()
router.GET("/", Anonymous)
router.GET("/admin/", BasicAuth(Admin, user, pass))
log.Fatal(http.ListenAndServe(":8080", router))
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ .Name }}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script>
function counter() {
document.getElementById("x").innerHTML = "x: " + document.querySelectorAll('.x').length;
document.getElementById("y").innerHTML = "y: " + document.querySelectorAll('.y').length;
document.getElementById("z").innerHTML = "z: " + document.querySelectorAll('.z').length;
}
</script>
</head>
<body onload="counter()">
{{ template "dashboard" }}
<nav class="navbar fixed-bottom">
<div class="container-fluid nav-justified">
<span id="x" class="navbar-brand nav-item"></span>
<span id="y" class="navbar-brand nav-item"></span>
<span id="z" class="navbar-brand nav-item"></span>
</div>
</nav>
</body>
</html>
admin.html
{{ define "dashboard" }}
<nav class="navbar">
<div class="container-fluid nav-justified">
<span class="nav-item">
<a class="navbar-brand" href="/a">a</a>
</span>
<span class="nav-item">
<a class="navbar-brand" href="/b">b</a>
</span>
<span class="nav-item">
<a class="navbar-brand" href="/c">c</a>
</span>
</div>
</nav>
{{ end }}
My assumption was that because I did not pass in the admin.html template while executing templates for the anonymous user, that the dashboard template would not be parsed. However, I run into this error:
template: index.html:18:14: executing "index.html" at <{{template "dashboard"}}>: template "dashboard" not defined
How do I fix this, or is there a better way to do this?
答案1
得分: 0
使用if
语句在条件满足时有条件地渲染dashboard
模板:
{{ if eq .Name "Admin" }} {{ template "dashboard" }} {{ end }}
而实践中的做法是只解析模板一次,而不是在每个请求上解析它:
package main
import (
"log"
"net/http"
"sync"
"text/template"
"github.com/julienschmidt/httprouter"
)
func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
user, password, hasAuth := r.BasicAuth()
if hasAuth && user == requiredUser && password == requiredPassword {
h(w, r, ps)
} else {
w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
}
}
func Anonymous(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
err := tmpl.Execute(w, map[string]string{"Name": "Anonymous"})
if err != nil {
log.Fatalln(err)
}
}
func Admin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
err := tmpl.Execute(w, map[string]string{"Name": "Admin"})
if err != nil {
log.Fatalln(err)
}
}
var (
tmpl *template.Template
tmplOnce sync.Once
)
func main() {
user := "admin"
pass := "1234"
tmplOnce.Do(func() {
tmpl = template.Must(template.ParseFiles("index.html", "admin.html"))
})
router := httprouter.New()
router.GET("/", Anonymous)
router.GET("/admin/", BasicAuth(Admin, user, pass))
log.Fatal(http.ListenAndServe(":8080", router))
}
英文:
Render the dashboard
template conditionally with an if
action:
{{ if eq .Name "Admin" }} {{ template "dashboard" }} {{ end }}
And the practice is to parse the template only once instead of parsing it on every request:
package main
import (
"log"
"net/http"
"sync"
"text/template"
"github.com/julienschmidt/httprouter"
)
func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
user, password, hasAuth := r.BasicAuth()
if hasAuth && user == requiredUser && password == requiredPassword {
h(w, r, ps)
} else {
w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
}
}
func Anonymous(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
err := tmpl.Execute(w, map[string]string{"Name": "Anonymous"})
if err != nil {
log.Fatalln(err)
}
}
func Admin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
err := tmpl.Execute(w, map[string]string{"Name": "Admin"})
if err != nil {
log.Fatalln(err)
}
}
var (
tmpl *template.Template
tmplOnce sync.Once
)
func main() {
user := "admin"
pass := "1234"
tmplOnce.Do(func() {
tmpl = template.Must(template.ParseFiles("index.html", "admin.html"))
})
router := httprouter.New()
router.GET("/", Anonymous)
router.GET("/admin/", BasicAuth(Admin, user, pass))
log.Fatal(http.ListenAndServe(":8080", router))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论