如何在Go HTML模板中同时传递多组变量实现页面多条件渲染?
Fixing Nested Rendering & Data Passing Issues in Go Template Execution
Let's break down what's going wrong here and fix it step by step:
Key Problems in Your Current Code
- Duplicate Request Method Check: The second
if r.Method != http.MethodPostblock will never run—you already return after the first check for GET requests, so your vehicle list is never passed to the template when it matters. - Inconsistent Data Types: You're trying to pass two separate data structures (
conditionsMapandcarSlice) to the same template. EachExecutecall overwrites the template context, and the template can't access both values from different sources at once.
Step 1: Define a Unified Template Data Struct
Create a struct that holds all the data your template needs. This lets you pass both the username and vehicle list in a single, consistent payload:
type TemplateData struct { Username string Vehicles []Vehicle }
Step 2: Rewrite the RemoveVehicle Handler
Adjust your handler to use this struct, fix the request flow, and ensure all necessary data is passed to the template in one execution:
func RemoveVehicle(w http.ResponseWriter, r *http.Request) { // Initialize our template data container data := TemplateData{} // Populate username from token username, _ := ExtractTokenUsername(r) data.Username = username // Parse template (for better performance, cache this globally instead of parsing on each request) t, err := template.ParseFiles("remove.html") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Handle GET request: render the form with vehicle data (if user is logged in) if r.Method == http.MethodGet { if username != "" { // Connect to database 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 carSlice []Vehicle // Fetch ONLY the current user's vehicles (added WHERE clause for security) sqlStatement := `SELECT * FROM Vehicle WHERE Username = ?` rows, err := db.Query(sqlStatement, username) if err != nil { panic(err) } defer rows.Close() for rows.Next() { var car Vehicle // Ensure scan order matches your Vehicle struct's field order! err := rows.Scan(&car.Id, &car.Date, &car.Brand, &car.Model, &car.Mileage, &car.Year, &car.rented, &car.Dayrate) if err != nil { panic(err) } carSlice = append(carSlice, car) } data.Vehicles = carSlice } // Execute template ONCE with all our combined data t.Execute(w, data) return } // Handle POST request: process vehicle deletion if r.Method == http.MethodPost { if username == "" { http.Error(w, "Access Denied", http.StatusForbidden) 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() id_ := r.FormValue("select") fmt.Println(id_) // Add Username check to prevent deleting other users' vehicles stmt, e := db.Prepare("DELETE FROM vehicle WHERE id=? AND Username = ?") ErrorCheck(e) _, err = stmt.Exec(id_, username) if err != nil { panic(err) } // Redirect back to the remove page after successful deletion http.Redirect(w, r, "/remove", http.StatusSeeOther) return } // Catch-all for unsupported HTTP methods http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) }
Step 3: Update the HTML Template
Adjust the template to access the vehicle list from the Vehicles field of our struct:
{{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}}
Key Improvements
- Single Template Execution: We now pass all necessary data in one struct and execute the template once, eliminating nested rendering issues.
- Secure Database Queries: Added
Usernamechecks to both vehicle fetch and deletion queries to prevent users from accessing or modifying other users' vehicles. - Cleaner Request Flow: Separated GET and POST logic clearly, with a redirect after deletion to avoid form resubmission issues.
内容的提问来源于stack exchange,提问作者Giuseppe Marziano
相关产品推荐
相关产品推荐

