解析带有绑定的数组表单元素

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

Parsing array form elements with bindings

问题

我正在尝试在Go中提交和解析一个表单,但无法正确解析表单字段。以下是我尝试的代码摘录。

formtest.go:

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net/http"
  6. "github.com/codegangsta/negroni"
  7. "github.com/davecgh/go-spew/spew"
  8. "github.com/julienschmidt/httprouter"
  9. "github.com/mholt/binding"
  10. "gopkg.in/unrolled/render.v1"
  11. )
  12. type FormInfo struct {
  13. Fields []string
  14. Action string
  15. PageTitle string
  16. Id string
  17. }
  18. func (f *FormInfo) FieldMap(*http.Request) binding.FieldMap {
  19. return binding.FieldMap{
  20. &f.Fields: "fields",
  21. &f.Action: "action",
  22. }
  23. }
  24. func formtest(
  25. resp http.ResponseWriter,
  26. req *http.Request,
  27. p httprouter.Params) {
  28. info := new(FormInfo)
  29. tkt := p.ByName("tkt")
  30. info.PageTitle = tkt
  31. info.Id = tkt
  32. if req.Method == "POST" {
  33. bind_err := binding.Bind(req, info)
  34. if bind_err.Handle(resp) {
  35. log.Println("Error decoding form contents")
  36. return
  37. }
  38. spew.Dump(info)
  39. }
  40. Render.HTML(resp, http.StatusOK, "formtest", info)
  41. return
  42. }
  43. var Render *render.Render
  44. func main() {
  45. router := httprouter.New()
  46. router.GET("/formtest", formtest)
  47. router.POST("/formtest", formtest)
  48. Render = render.New(render.Options{
  49. Layout: "layout",
  50. IndentJSON: true,
  51. IndentXML: true,
  52. HTMLContentType: "text/html",
  53. IsDevelopment: true,
  54. })
  55. n := negroni.New(
  56. negroni.NewRecovery(),
  57. negroni.NewLogger(),
  58. negroni.NewStatic(http.Dir("static")),
  59. )
  60. n.UseHandler(router)
  61. n.Run(fmt.Sprintf(":%d", 3000))
  62. }

templates/layout.tmpl:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>{{ .PageTitle }}</title>
  5. <meta http-equiv="Content-Type" content="text/html;" charset="utf-8">
  6. <meta charset="UTF-8">
  7. <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
  8. <link rel="apple-touch-icon" href="/mobile.png" />
  9. <meta name="viewport"
  10. content="initial-scale=1.0,width=device-width,user-scalable=no">
  11. <meta name="generator" content="Go">
  12. <link rel="stylesheet" href="/base.css" type="text/css">
  13. </head>
  14. <body>
  15. <div class="mainbody">
  16. {{ yield }}
  17. </div>
  18. </body>
  19. </html>

templates/formtest.tmpl:

  1. <h1>{{ .PageTitle }}</h1>
  2. <form action="/formtest/{{ .Id }}" method="POST">
  3. <div class="details">
  4. <label>Question 1</label>
  5. <input type="text" name="fields[0]" value="value 1" />
  6. </div>
  7. <div class="details">
  8. <label>Question 2</label>
  9. <input type="text" name="fields[1]" value="value 2" />
  10. </div>
  11. <div class="details">
  12. <input type="submit" name="action" value="save" />
  13. </div>
  14. </form>

步骤:

  1. 运行 go run formtest.go
  2. 打开浏览器,访问 http://127.0.0.1:3000/formtest
  3. 提交表单
  4. 检查控制台日志。

观察结果:

  1. (*main.FormInfo)(0xc820066c30)({
  2. Fields: ([]string) <nil>,
  3. Action: (string) (len=4) "save",
  4. PageTitle: (string) "",
  5. Id: (string) ""
  6. })

期望结果:

  1. Fields: ([]string) <包含两个提交值>,

但是当我尝试打印 Fields 的内容时,它是 nil。我做错了什么?

英文:

I am trying to submit and parse a form in go and I am failing to parse the form fields properly.
Here is an excerpt of the code I am trying.

formtest.go :
package main

  1. import (
  2. &quot;fmt&quot;
  3. &quot;log&quot;
  4. &quot;net/http&quot;
  5. &quot;github.com/codegangsta/negroni&quot;
  6. &quot;github.com/davecgh/go-spew/spew&quot;
  7. &quot;github.com/julienschmidt/httprouter&quot;
  8. &quot;github.com/mholt/binding&quot;
  9. &quot;gopkg.in/unrolled/render.v1&quot;
  10. )
  11. type FormInfo struct {
  12. Fields []string
  13. Action string
  14. PageTitle string
  15. Id string
  16. }
  17. func (f *FormInfo) FieldMap(*http.Request) binding.FieldMap {
  18. return binding.FieldMap{
  19. &amp;f.Fields: &quot;fields&quot;,
  20. &amp;f.Action: &quot;action&quot;,
  21. }
  22. }
  23. func formtest(
  24. resp http.ResponseWriter,
  25. req *http.Request,
  26. p httprouter.Params) {
  27. // var ticket Ticket
  28. info := new(FormInfo)
  29. tkt := p.ByName(&quot;tkt&quot;)
  30. info.PageTitle = tkt
  31. info.Id = tkt
  32. if req.Method == &quot;POST&quot; {
  33. bind_err := binding.Bind(req, info)
  34. if bind_err.Handle(resp) {
  35. log.Println(&quot;Error decoding form contents&quot;)
  36. return
  37. }
  38. spew.Dump(info)
  39. }
  40. Render.HTML(resp, http.StatusOK, &quot;formtest&quot;, info)
  41. return
  42. }
  43. var Render *render.Render
  44. func main() {
  45. router := httprouter.New()
  46. router.GET(&quot;/formtest&quot;, formtest)
  47. router.POST(&quot;/formtest&quot;, formtest)
  48. Render = render.New(render.Options{
  49. Layout: &quot;layout&quot;,
  50. IndentJSON: true,
  51. IndentXML: true,
  52. HTMLContentType: &quot;text/html&quot;,
  53. IsDevelopment: true,
  54. })
  55. n := negroni.New(
  56. negroni.NewRecovery(),
  57. negroni.NewLogger(),
  58. negroni.NewStatic(http.Dir(&quot;static&quot;)),
  59. )
  60. n.UseHandler(router)
  61. n.Run(fmt.Sprintf(&quot;:%d&quot;, 3000))
  62. }

templates/layout.tmpl :

  1. &lt;!DOCTYPE html&gt;
  2. &lt;html lang=&quot;en&quot;&gt;
  3. &lt;head&gt;
  4. &lt;title&gt;{{ .PageTitle }}&lt;/title&gt;
  5. &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;&quot; charset=&quot;utf-8&quot;&gt;
  6. &lt;meta charset=&quot;UTF-8&quot;&gt;
  7. &lt;link rel=&quot;shortcut icon&quot; type=&quot;image/x-icon&quot; href=&quot;/favicon.ico&quot; /&gt;
  8. &lt;link rel=&quot;apple-touch-icon&quot; href=&quot;/mobile.png&quot; /&gt;
  9. &lt;meta name=&quot;viewport&quot;
  10. content=&quot;initial-scale=1.0,width=device-width,user-scalable=no&quot;&gt;
  11. &lt;meta name=&quot;generator&quot; content=&quot;Go&quot;&gt;
  12. &lt;link rel=&quot;stylesheet&quot; href=&quot;/base.css&quot; type=&quot;text/css&quot;&gt;
  13. &lt;/head&gt;
  14. &lt;body&gt;
  15. &lt;div class=&quot;mainbody&quot;&gt;
  16. {{ yield }}
  17. &lt;/div&gt;
  18. &lt;/body&gt;
  19. &lt;/html&gt;

templates/formtest.tmpl :

  1. &lt;h1&gt;{{ .PageTitle }}&lt;/h1&gt;
  2. &lt;form action=&quot;/formtest/{{ .Id }}&quot; method=&quot;POST&quot;&gt;
  3. &lt;div class=&quot;details&quot;&gt;
  4. &lt;label&gt;Question 1&lt;/label&gt;
  5. &lt;input type=&quot;text&quot; name=&quot;fields[0]&quot; value=&quot;value 1&quot; /&gt;
  6. &lt;/div&gt;
  7. &lt;div class=&quot;details&quot;&gt;
  8. &lt;label&gt;Question 2&lt;/label&gt;
  9. &lt;input type=&quot;text&quot; name=&quot;fields[1]&quot; value=&quot;value 2&quot; /&gt;
  10. &lt;/div&gt;
  11. &lt;div class=&quot;details&quot;&gt;
  12. &lt;input type=&quot;submit&quot; name=&quot;action&quot; value=&quot;save&quot; /&gt;
  13. &lt;/div&gt;
  14. &lt;/form&gt;

Procedure:

  1. go run formtest.go
  2. Open browser and go to http://127.0.0.1:3000/formtest
  3. Submit the form
  4. Check console for the logs.

Observation :

  1. (*main.FormInfo)(0xc820066c30)({
  2. Fields: ([]string) &lt;nil&gt;,
  3. Action: (string) (len=4) &quot;save&quot;,
  4. PageTitle: (string) &quot;&quot;,
  5. Id: (string) &quot;&quot;
  6. })

Expectation :

  1. Fields: ([]string) &lt;contains two values submitted&gt;,

But when I try to print the contents of Fields, it is nil.
What am I doing wrong?

答案1

得分: 1

绑定不起作用。您表单的字段 - name = "fields [1]" 和 name = "fields [0]" 是相互独立的,因此对于每个字段,您的结构应包含自己的字段:

type FormInfo struct {
Fields1 string
Fields2 string
Action string
PageTitle string
Id string
}

在处理程序中分别为它们赋值:

...
&f.Fields1: "fields[0]",
&f.Fields2: "fields[1]",
&f.Action: "action",
...

结果将是:

(*main.FormInfo)(0xc08200aa50)({
Fields1: (string) (len=7) "value 1",
Fields2: (string) (len=7) "value 2",
Action: (string) (len=4) "save",
PageTitle: (string) "",
Id: (string) ""
})
编辑:

如果您更改表单中的代码:

...
<input type="text" name="fields"...
<input type="text" name="fields"...

您可以获得:

info.Fields = [value 1 value 2]

而无需更改其原始代码。

英文:

Binding so not work. The fields of your form - name = "fields [1]" and
name = "fields [0]" are independent from each other, so for each of them your structure should contain its own field:

  1. type FormInfo struct {
  2. Fields1 string
  3. Fields2 string
  4. Action string
  5. PageTitle string
  6. Id string
  7. }

respectively, in the handler:

  1. ...
  2. &amp;f.Fields1: &quot;fields[0]&quot;,
  3. &amp;f.Fields2: &quot;fields[1]&quot;,
  4. &amp;f.Action: &quot;action&quot;,
  5. ...

As a result, the output will be:

  1. (*main.FormInfo)(0xc08200aa50)({
  2. Fields1: (string) (len=7) &quot;value 1&quot;,
  3. Fields2: (string) (len=7) &quot;value 2&quot;,
  4. Action: (string) (len=4) &quot;save&quot;,
  5. PageTitle: (string) &quot;&quot;,
  6. Id: (string) &quot;&quot;
  7. })

EDIT:

If you change the code in the form on the

  1. ...
  2. &lt;input type=&quot;text&quot; name=&quot;fields&quot;...
  3. &lt;input type=&quot;text&quot; name=&quot;fields&quot;...

you can get

  1. info.Fields = [value 1 value 2]

without changing its original code.

huangapple
  • 本文由 发表于 2015年9月28日 12:09:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/32815561.html
匿名

发表评论

匿名网友

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

确定