英文:
How to execute multiple variables in HTML Go Template?
问题
我尝试查看其他问题,但它们似乎不能解决我的情况。
我基本上需要在我的HTML页面上有两个if语句,但是每当我触发第二个tmpl.Execute()
时,我实际上会在这些if语句中嵌入相同的页面。
这是我试图使其工作的函数:
func RemoveVehicle(w http.ResponseWriter, r *http.Request) {
conditionsMap := map[string]interface{}{}
username, _ := ExtractTokenUsername(r)
if username != "" {
conditionsMap["Username"] = username
}
t, err := template.ParseFiles("remove.html")
if err != nil {
http.Error(w, err.Error(), 500)
return
}
if r.Method != http.MethodPost {
t.Execute(w, conditionsMap) //在这里,我试图检查用户是否已登录,如果没有,则返回一个触发else语句的false布尔值
return
}
db, err := sql.Open("mysql", "root:*******@tcp(127.0.0.1:3306)/my_db")
if err != nil {
fmt.Println("Connection Failed.")
panic(err.Error())
}
defer db.Close()
var car Vehicle
sqlStatement := `SELECT * FROM Vehicle`
rows, err := db.Query(sqlStatement)
if err != nil {
panic(err)
}
defer rows.Close()
var carSlice []Vehicle
for rows.Next() {
rows.Scan(&car.Id, &car.Date, &car.Brand, &car.Model, &car.Mileage, &car.Year, &car.rented, &car.Dayrate)
carSlice = append(carSlice, car)
}
if r.Method != http.MethodPost {
t.Execute(w, carSlice) //然后在这里,我试图用表中的几行填充表单选择
return
}
var id_ = r.FormValue("select")
fmt.Println(id_)
stmt, e := db.Prepare("DELETE FROM vehicle WHERE id=?")
ErrorCheck(e)
stmt.Exec(id_)
}
我已经注释掉了我试图同时使其工作的两个部分,但它们单独工作。
这是相关的HTML代码:
{{if .Username}}
<div><img src="images/kogdpilnmzhz9rhzceo2.png" alt="" width="65" height="65" class="addV_label"/></div>
<hr style="height:5px">
<form action="/remove" method="POST" source="custom" name="form">
<input type="hidden" name="xss-token" value=""/>
<div class="form-group">
<div>
<label class="addV_label">Select Vehicle </label>
<select name="select" class="form-control loginInput2" required="required">
{{range .}}
<option value="{{.Id}}">{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | £{{.Dayrate}}/pd</option>
{{end}}
</select>
</div>
</div>
<div>
<button class="btn-block frgt_1 btn addV_btn" type="submit" value="remove">REMOVE</button>
</div>
</form>
{{else}}
<p> Access Denied, please login.<a href="/login">Login</a></p>
{{end}}
我尝试使用一个结构体,但carSlice
已经是一个结构体,而conditionMap
是一个映射。
解决这种情况的最佳方法是什么?
英文:
I've tried looking at the other questions, and they don't seem to help my situation.
I essentially need to have 2 if statements on my HTML page, but whenever I trigger the second tmpl.Execute()
I essentially get the same page embedded within those if statements.
Here is a function that I am trying to get working:
func RemoveVehicle(w http.ResponseWriter, r *http.Request) {
conditionsMap := map[string]interface{}{}
username, _ := ExtractTokenUsername(r)
if username != "" {
conditionsMap["Username"] = username
}
t, err := template.ParseFiles("remove.html")
if err != nil {
http.Error(w, err.Error(), 500)
return
}
if r.Method != http.MethodPost {
t.Execute(w, conditionsMap) //Here I am trying to check to see if the user is logged in, and if not to return a false boolean that will trigger the else statement
return
}
db, err := sql.Open("mysql", "root:*******@tcp(127.0.0.1:3306)/my_db")
if err != nil {
fmt.Println("Connection Failed.")
panic(err.Error())
}
defer db.Close()
var car Vehicle
sqlStatement := `SELECT * FROM Vehicle`
rows, err := db.Query(sqlStatement)
if err != nil {
panic(err)
}
defer rows.Close()
var carSlice []Vehicle
for rows.Next() {
rows.Scan(&car.Id, &car.Date, &car.Brand, &car.Model, &car.Mileage, &car.Year, &car.rented, &car.Dayrate)
carSlice = append(carSlice, car)
}
if r.Method != http.MethodPost {
t.Execute(w, carSlice) // Then here I am trying to populate the form select with a few rows from a table
return
}
var id_ = r.FormValue("select")
fmt.Println(id_)
stmt, e := db.Prepare("DELETE FROM vehicle WHERE id=?")
ErrorCheck(e)
stmt.Exec(id_)
}
I have commented out the 2 parts that I am trying to get working simultaneously, but they work individually.
Here is the relevant HTML:
{{if .Username}}
<div><img src="images/kogdpilnmzhz9rhzceo2.png" alt="" width="65" height="65" class="addV_label"/></div>
<hr style="height:5px">
<form action="/remove" method="POST" source="custom" name="form">
<input type="hidden" name="xss-token" value=""/>
<div class="form-group">
<div>
<label class="addV_label">Select Vehicle&nbsp;</label>
<select name="select" class="form-control loginInput2" required="required">
{{range .}}
<option value="{{.Id}}">{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | £{{.Dayrate}}/pd</option>
{{end}}
</select>
</div>
</div>
<div>
<button class="btn-block frgt_1 btn addV_btn" type="submit" value="remove">REMOVE</button>
</div>
</form>
{{else}}
<p> Access Denied, please login.<a href="/login">Login</a></p>
{{end}}
I've tried to use a struct, but the carSlice
is already a struct and conditionMap
is a map.
What would be the best solution to tackling this situation?
答案1
得分: 2
首先,建议在程序启动时只初始化*template.Template
类型和*sql.DB
连接池一次。这两种类型都可以安全地并发使用,因此可以同时被多个处理程序使用。
var (
removeTemplate *template.Template
db *sql.DB
)
func init() {
var err error
removeTemplate, err = template.ParseFiles("remove.html")
if err != nil {
panic(err)
}
db, err = sql.Open("mysql", "root:*******@tcp(127.0.0.1:3306)/my_db")
if err != nil {
panic(err)
} else if err := db.Ping(); err != nil {
panic(err)
}
}
现在你的处理程序可以如下所示:
func RemoveVehicle(w http.ResponseWriter, r *http.Request) {
// 检查用户是否已登录
username, _ := ExtractTokenUsername(r)
if len(username) == 0 {
// 如果没有登录,渲染没有数据的模板,这将显示模板中的“请登录”部分
if err := removeTemplate.Execute(w, nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
return
}
switch r.Method {
// 如果方法是GET,显示可用车辆列表
case http.MethodGet:
// 从数据库中选择车辆
rows, err := db.Query(`SELECT * FROM Vehicle`)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer rows.Close()
// 扫描行
var vehicles []Vehicle
for rows.Next() {
var v Vehicle
err := rows.Scan(&v.Id, &v.Date, &v.Brand, &v.Model, &v.Mileage, &v.Year, &v.rented, &v.Dayrate)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
vehicles = append(vehicles, v)
}
if err := rows.Err(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 现在使用刚刚从数据库中检索到的数据渲染模板
data := map[string]interface{}{
"Username": username,
"Vehicles": vehicles,
}
if err := removeTemplate.Execute(w, data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
// 如果方法是POST,删除车辆
case http.MethodPost:
var id = r.FormValue("select")
if _, err := db.Exec("DELETE FROM vehicle WHERE id=?", id); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
在模板中,由处理程序传递的数据是一个带有Username
和Vehicles
键的映射,你需要对.Vehicles
进行range
迭代,而不仅仅是.
。
{{if .Username}}
<div><img src="images/kogdpilnmzhz9rhzceo2.png" alt="" width="65" height="65" class="addV_label"/></div>
<hr style="height:5px">
<form action="/remove" method="POST" source="custom" name="form">
<input type="hidden" name="xss-token" value=""/>
<div class="form-group">
<div>
<label class="addV_label">Select Vehicle </label>
<select name="select" class="form-control loginInput2" required="required">
{{range .Vehicles}}
<option value="{{.Id}}">{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | £{{.Dayrate}}/pd</option>
{{end}}
</select>
</div>
</div>
<div>
<button class="btn-block frgt_1 btn addV_btn" type="submit" value="remove">REMOVE</button>
</div>
</form>
{{else}}
<p> Access Denied, please login.<a href="/login">Login</a></p>
{{end}}
英文:
First off, it is recommended to initialize the *template.Template
types and the *sql.DB
connection pool only once, during program start up. Both types are safe for concurrent use and can therefore be used by multiple handlers simultaneously.
var (
removeTemplate *template.Template
db *sql.DB
)
func init() {
var err error
removeTemplate, err = template.ParseFiles("remove.html")
if err != nil {
panic(err)
}
db, err = sql.Open("mysql", "root:*******@tcp(127.0.0.1:3306)/my_db")
if err != nil {
panic(err)
} else if err := db.Ping(); err != nil {
panic(err)
}
}
Now your handler can look something like the following:
func RemoveVehicle(w http.ResponseWriter, r *http.Request) {
// check if the user is logged in
username, _ := ExtractTokenUsername(r)
if len(username) == 0 {
// if not, render the template with no data, this
// will show the "please login" part of your template
if err := removeTemplate.Execute(w, nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
return
}
switch r.Method {
// if the method is GET, show the list of vehicles available
case http.MethodGet:
// select vehicles from db
rows, err := db.Query(`SELECT * FROM Vehicle`)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer rows.Close()
// scan rows
var vehicles []Vehicle
for rows.Next() {
var v Vehicle
err := rows.Scan(&v.Id, &v.Date, &v.Brand, &v.Model, &v.Mileage, &v.Year, &v.rented, &v.Dayrate)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
vehicles = append(vehicles, v)
}
if err := rows.Err(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// now render the template with the data
// that you just retrieved from the database
data := map[string]interface{}{
"Username": username,
"Vehicles": vehicles,
}
if err := removeTemplate.Execute(w, data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
// if the method is POST, delete the vehicle
case http.MethodPost {
var id = r.FormValue("select")
if _, err := db.Exec("DELETE FROM vehicle WHERE id=?", id); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
And in your template, since a data passed in by the handler is a map with Username
and Vehicles
keys, you need to range
over .Vehicles
and not just the .
.
{{if .Username}}
<div><img src="images/kogdpilnmzhz9rhzceo2.png" alt="" width="65" height="65" class="addV_label"/></div>
<hr style="height:5px">
<form action="/remove" method="POST" source="custom" name="form">
<input type="hidden" name="xss-token" value=""/>
<div class="form-group">
<div>
<label class="addV_label">Select Vehicle&nbsp;</label>
<select name="select" class="form-control loginInput2" required="required">
{{range .Vehicles}}
<option value="{{.Id}}">{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | £{{.Dayrate}}/pd</option>
{{end}}
</select>
</div>
</div>
<div>
<button class="btn-block frgt_1 btn addV_btn" type="submit" value="remove">REMOVE</button>
</div>
</form>
{{else}}
<p> Access Denied, please login.<a href="/login">Login</a></p>
{{end}}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论