英文:
Accessing struct variable outside of {{range .}} scope in golang html template
问题
回复
{{$threadID := .ThreadID}}
{{.Subject}}
{{.Name}}
{{.Text}}
{{end}}
我有这个模板,在页面顶部有一个表单,需要从发送的任何一个帖子中获取threadID(它们都是相同的,是具有特定threadID的所有帖子的切片),这显然行不通,我唯一的其他想法是类似于
{{range .}}
{{if $threadID == nil}}
$threadID := .ThreadID
//构建与上面相同的表单
{{end}}
{{.Subject}}
{{.Name}}
{{.Text}}
{{end}}
如果上面的任何内容不清楚,这是Post结构和方法。
type Post struct {
threadID int
subject string
name string
text string
date_posted string
}
func (p *Post) ThreadID() int { return p.threadID }
func (p *Post) Subject() string { return p.subject }
func (p *Post) Name() string { return p.name }
func (p *Post) Text() string { return p.text }
func (p *Post) DatePosted() string { return p.date_posted }
以及发送到模板的帖子切片的来源。
threadID := r.URL.Path[len("/reply/"):]
replies, err := i.db.Query("SELECT * FROM latest_threads where thread_id="+threadID);
英文:
<!DOCTYPE html>
<html>
<head>
<title> Test </title>
</head>
<body>
<div>
<h2>Reply</h2>
<form action="/post/{{$threadID}}" method="POST">
<input type="text" name="subject" />
<input type="text" name="name" value="Anonymous" />
<input type="text" name="message" />
<input type="submit" value="submit" />
</form>
</div>
<div>
{{range .}}
{{$threadID := .ThreadID}}
<h3>{{.Subject}}</h3>
<h3>{{.Name}}</h3>
<div>{{.DatePosted}}</div>
<div><p>{{.Text}}</p></div>
<br /><br />
{{end}}
</div>
</body>
</html>
I have this template, there is a form at the top of the page that requires the threadID from ANY one of the Posts sent (they're all the same, a slice of all posts with a certain threadID), this obviously doesn't work, my only other idea was something along the lines of
{{range .}}
{{if $threadID == nil}}
$threadID := .ThreadID
//build the form same as above
{{end}}
<h3>{{.Subject}}</h3>
<h3>{{.Name}}</h3>
<div>{{.DatePosted}}</div>
<div><p>{{.Text}}</p></div>
<br /><br />
{{end}}
Here is the Post structure and methods if any of the above is unclear.
type Post struct {
threadID int
subject string
name string
text string
date_posted string
}
func (p *Post) ThreadID() int { return p.threadID }
func (p *Post) Subject() string { return p.subject }
func (p *Post) Name() string { return p.name }
func (p *Post) Text() string { return p.text }
func (p *Post) DatePosted() string { return p.date_posted }
And the origin of the slice of posts sent to the template
threadID := r.URL.Path[len("/reply/"):]
replies, err := i.db.Query("SELECT * FROM latest_threads where thread_id="+threadID);
答案1
得分: 5
如果只能从帖子类型本身中获取线程ID,请考虑将帖子列表转换为单独的类型。给它一个ThreadId方法,该方法简单地返回它包含的第一个帖子的ID,如果没有帖子存在,则返回零。
type PostList []*Post
func (p PostList) ThreadId() int {
if len(p) == 0 {
return 0
}
return p[0].ThreadId
}
将此列表传递到模板中。现在,您可以在模板中的{{range .}}
之外的任何地方引用它。
<form action="/post/{{.ThreadID}}" method="POST">
漏洞警告
顺便提一下,Little Bobby Tables在SQL查询中存在问题。如果您只是将其作为一个快速示例发布,那么可能没有问题。如果不是,请注意您的代码可能会导致SQL注入攻击。如果线程ID是数字,请确保在将其传递到SQL查询之前将其解析为数字。例如:对输入进行清理处理。
英文:
If the Thread Id can only be retrieved from the Post type itself, consider turning your slice of posts into a separate type. Give it a ThreadID method, which simply returns the id for the first post it contains, or zero if none exist.
type PostList []*Post
func (p PostList) ThreadId() int {
if len(p) == 0 {
return 0
}
return p[0].ThreadId
}
Pass this list into the template. Now you can reference it from the template, anywhere outside of the {{range .}}
clause.
<form action="/post/{{.ThreadID}}" method="POST">
Exploit warning
As a side note, Little Bobby Tables has an issue with the SQL query.
It's possible you are just posting it as a quick example. If not, be advised that your code is a recipe for SQL injection exploits. If the thread ID is numeric, then ensure you parse it as such, before passing it into the SQL query. E.g.: Sanitize your inputs.
答案2
得分: 4
你可以将所有内容作为一个结构体传递,如下所示:
layoutData := struct {
ThreadID int
Posts []Post
} {
ThreadID: threadID,
Posts: Posts,
}
然后可以使用以下代码:
<!DOCTYPE html>
<html>
<head>
<title> Test </title>
</head>
<body>
<div>
<h2>Reply</h2>
<form action="/post/{{ .ThreadID }}" method="POST">
<input type="text" name="subject" />
<input type="text" name="name" value="Anonymous" />
<input type="text" name="message" />
<input type="submit" value="submit" />
</form>
</div>
<div>
{{range $post := .Posts}}
<h3>{{$post.Subject}}</h3>
<h3>{{$post.Name}}</h3>
<div>{{$post.DatePosted}}</div>
<div><p>{{$post.Text}}</p></div>
<br /><br />
{{end}}
</div>
</body>
请注意,这只是一个示例代码,具体实现可能需要根据你的需求进行调整。
英文:
You can pass it all as one struct like so:
layoutData := struct {
ThreadID int
Posts []Post
} {
ThreadID: threadID,
Posts: Posts,
}
Then something like this will work
<!DOCTYPE html>
<html>
<head>
<title> Test </title>
</head>
<body>
<div>
<h2>Reply</h2>
<form action="/post/{{ .ThreadID }}" method="POST">
<input type="text" name="subject" />
<input type="text" name="name" value="Anonymous" />
<input type="text" name="message" />
<input type="submit" value="submit" />
</form>
</div>
<div>
{{range $post := .Posts}}
<h3>{{ $post.Subject}}</h3>
<h3>{{$post.Name}}</h3>
<div>{{$post.DatePosted}}</div>
<div><p>{{$post.Text}}</p></div>
<br /><br />
{{end}}
</div>
</body>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论