如何在HTML Go模板中执行多个变量?

huangapple go评论76阅读模式
英文:

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&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}}

我尝试使用一个结构体,但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 != &quot;&quot; {
conditionsMap[&quot;Username&quot;] = username
}
t, err := template.ParseFiles(&quot;remove.html&quot;)
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(&quot;mysql&quot;, &quot;root:*******@tcp(127.0.0.1:3306)/my_db&quot;)
if err != nil {
fmt.Println(&quot;Connection Failed.&quot;)
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(&amp;car.Id, &amp;car.Date, &amp;car.Brand, &amp;car.Model, &amp;car.Mileage, &amp;car.Year, &amp;car.rented, &amp;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(&quot;select&quot;)
fmt.Println(id_)
stmt, e := db.Prepare(&quot;DELETE FROM vehicle WHERE id=?&quot;)
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}}
&lt;div&gt;&lt;img src=&quot;images/kogdpilnmzhz9rhzceo2.png&quot; alt=&quot;&quot; width=&quot;65&quot; height=&quot;65&quot; class=&quot;addV_label&quot;/&gt;&lt;/div&gt;
&lt;hr style=&quot;height:5px&quot;&gt;
&lt;form action=&quot;/remove&quot; method=&quot;POST&quot; source=&quot;custom&quot; name=&quot;form&quot;&gt;
&lt;input type=&quot;hidden&quot; name=&quot;xss-token&quot; value=&quot;&quot;/&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;div&gt;
&lt;label class=&quot;addV_label&quot;&gt;Select Vehicle&amp;nbsp;&lt;/label&gt;
&lt;select name=&quot;select&quot; class=&quot;form-control loginInput2&quot; required=&quot;required&quot;&gt;
{{range .}}
&lt;option value=&quot;{{.Id}}&quot;&gt;{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | &#163;{{.Dayrate}}/pd&lt;/option&gt;
{{end}}
&lt;/select&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;button class=&quot;btn-block frgt_1 btn addV_btn&quot; type=&quot;submit&quot; value=&quot;remove&quot;&gt;REMOVE&lt;/button&gt;
&lt;/div&gt;
&lt;/form&gt;
{{else}}
&lt;p&gt; Access Denied, please login.&lt;a href=&quot;/login&quot;&gt;Login&lt;/a&gt;&lt;/p&gt;
{{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)
		}
	}
}

在模板中,由处理程序传递的数据是一个带有UsernameVehicles键的映射,你需要对.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&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}}
英文:

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(&quot;remove.html&quot;)
	if err != nil {
		panic(err)
	}

	db, err = sql.Open(&quot;mysql&quot;, &quot;root:*******@tcp(127.0.0.1:3306)/my_db&quot;)
	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 &quot;please login&quot; 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(&amp;v.Id, &amp;v.Date, &amp;v.Brand, &amp;v.Model, &amp;v.Mileage, &amp;v.Year, &amp;v.rented, &amp;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{}{
			&quot;Username&quot;: username,
			&quot;Vehicles&quot;: 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(&quot;select&quot;)
		if _, err := db.Exec(&quot;DELETE FROM vehicle WHERE id=?&quot;, 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}}
&lt;div&gt;&lt;img src=&quot;images/kogdpilnmzhz9rhzceo2.png&quot; alt=&quot;&quot; width=&quot;65&quot; height=&quot;65&quot; class=&quot;addV_label&quot;/&gt;&lt;/div&gt;
&lt;hr style=&quot;height:5px&quot;&gt;
&lt;form action=&quot;/remove&quot; method=&quot;POST&quot; source=&quot;custom&quot; name=&quot;form&quot;&gt;
	&lt;input type=&quot;hidden&quot; name=&quot;xss-token&quot; value=&quot;&quot;/&gt;
	&lt;div class=&quot;form-group&quot;&gt;
		&lt;div&gt;
			&lt;label class=&quot;addV_label&quot;&gt;Select Vehicle&amp;nbsp;&lt;/label&gt;
			&lt;select name=&quot;select&quot; class=&quot;form-control loginInput2&quot; required=&quot;required&quot;&gt;
				{{range .Vehicles}}
				&lt;option value=&quot;{{.Id}}&quot;&gt;{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | &#163;{{.Dayrate}}/pd&lt;/option&gt;
				{{end}}
			&lt;/select&gt;
		&lt;/div&gt;
	&lt;/div&gt;
	&lt;div&gt;
		&lt;button class=&quot;btn-block frgt_1 btn addV_btn&quot; type=&quot;submit&quot; value=&quot;remove&quot;&gt;REMOVE&lt;/button&gt;
	&lt;/div&gt;
&lt;/form&gt;
{{else}}
&lt;p&gt; Access Denied, please login.&lt;a href=&quot;/login&quot;&gt;Login&lt;/a&gt;&lt;/p&gt;
{{end}}

huangapple
  • 本文由 发表于 2022年1月30日 16:58:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/70913226.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定