Beego会话不会自动将数据传递给模板

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

Beego Session Not Passing Data to Template Automatically

问题

在使用this.GetSession("session_key")获取类型为map[string]interface{}的会话信息后,我必须显式设置上下文并对会话进行类型断言,以便将数据明确传递给模板。

  1. // 获取会话
  2. profile := this.GetSession("profile")
  3. // 必须将数据添加到模板的上下文中
  4. this.Data["nickname"] = profile.(map[string]interface{})["nickname"].(string)
  5. this.Data["picture"] = profile.(map[string]interface{})["picture"].(string)
  6. // 渲染模板
  7. this.TplNames = "user.html"

会话数据(类型为map[string]interface{})如下所示:

  1. {"nickname": "joe", "picture": "urltotheimg"}

然而,根据Beego的会话文档,似乎会话会隐式传递,无需进行任何类型断言或上下文传递(模板可以直接访问会话值,例如{{.nickname}}{{.picture}})。

这是在重定向到/user之前设置会话的控制器:

  1. // 继承Beego的基础控制器
  2. type MyController struct {
  3. beego.Controller
  4. }
  5. func (this *MyController) Get() {
  6. // 在此处获取令牌的代码
  7. // 获取用户信息
  8. client := conf.Client(oauth2.NoContext, token)
  9. resp, err := client.Get("https://" + domain + "/userinfo")
  10. if err != nil {
  11. this.Redirect("/error", 500)
  12. return
  13. }
  14. // 读取用户信息的主体
  15. raw, err := ioutil.ReadAll(resp.Body)
  16. defer resp.Body.Close()
  17. if err != nil {
  18. this.Redirect("/error", 500)
  19. return
  20. }
  21. // 反序列化配置文件的JSON
  22. var profile map[string]interface{}
  23. if err := json.Unmarshal(raw, &profile); err != nil {
  24. this.Redirect("/error", 500)
  25. return
  26. }
  27. // 将信息保存到会话中
  28. this.SetSession("profile", profile)
  29. // 重定向到/user
  30. this.Redirect("/user", 301)
  31. }

这是/user的控制器:

  1. type UserController struct {
  2. beego.Controller
  3. }
  4. func (this *UserController) Get() {
  5. // 获取保存的会话
  6. profile := this.GetSession("profile")
  7. // 如果不在此处设置模板数据,会话数据将无法在user.html中使用
  8. this.Data["nickname"] = profile.(map[string]interface{})["nickname"].(string)
  9. this.Data["picture"] = profile.(map[string]interface{})["picture"].(string)
  10. this.TplNames = "user.html"
  11. }

只有这样,我才能将模板映射到数据,如下所示:

  1. <img src="{{ .picture }}">
  2. <p>Hello, {{ .nickname }}</p>

我相当确定需要设置模板数据,只是不确定为什么上述文档没有这样做。

如果有任何帮助,将不胜感激。

英文:

Upon getting session information of type map[string]interface{} with this.GetSession(&quot;session_key&quot;), I did have to explicitly set the context and type assert the session like this in order to explicitly pass the data to the template.

  1. // Get the session
  2. profile := this.GetSession(&quot;profile&quot;)
  3. // Have to add data to the template&#39;s context
  4. this.Data[&quot;nickname&quot;] = profile.(map[string]interface{})[&quot;nickname&quot;].(string)
  5. this.Data[&quot;picture&quot;] = profile.(map[string]interface{})[&quot;picture&quot;].(string)
  6. // Render template
  7. this.TplNames = &quot;user.html&quot;

The session data (type map[string]interface{}) looks like this:

  1. {&quot;nickname&quot;: &quot;joe&quot;, &quot;picture&quot;: &quot;urltotheimg&quot;}

However, according to the Beego's session <a href="http://beego.me/docs/mvc/controller/session.md">doc</a>, it looks like the session is passed implicitly without any need of type assertions or context passing (the template has immediate access to session values i.e. {{.nickname}} and {{.picture}})

This is the controller setting the session before redirecting to /user

  1. // Inherit beego&#39;s base controller
  2. type MyController struct {
  3. beego.Controller
  4. }
  5. func (this *MyController) Get() {
  6. // code for getting token here
  7. // Getting the User information
  8. client := conf.Client(oauth2.NoContext, token)
  9. resp, err := client.Get(&quot;https://&quot; + domain + &quot;/userinfo&quot;)
  10. if err != nil {
  11. this.Redirect(&quot;/error&quot;, 500)
  12. return
  13. }
  14. // Reading the body for user&#39;s information
  15. raw, err := ioutil.ReadAll(resp.Body)
  16. defer resp.Body.Close()
  17. if err != nil {
  18. this.Redirect(&quot;/error&quot;, 500)
  19. return
  20. }
  21. // Unmarshalling the JSON of the Profile
  22. var profile map[string]interface{}
  23. if err := json.Unmarshal(raw, &amp;profile); err != nil {
  24. this.Redirect(&quot;/error&quot;, 500)
  25. return
  26. }
  27. // Saving the information to the session.
  28. this.SetSession(&quot;profile&quot;, profile)
  29. // redirect to /user
  30. this.Redirect(&quot;/user&quot;, 301)
  31. }

This is the controller of "/user"

  1. type UserController struct {
  2. beego.Controller
  3. }
  4. func (this *UserController) Get() {
  5. // get the saved session
  6. profile := this.GetSession(&quot;profile&quot;)
  7. // without setting the template data here, the session data won&#39;t be
  8. // available in user.html
  9. this.Data[&quot;nickname&quot;] = profile.(map[string]interface{})[&quot;nickname&quot;].(string)
  10. this.Data[&quot;picture&quot;] = profile.(map[string]interface{})[&quot;picture&quot;].(string)
  11. this.TplNames = &quot;user.html&quot;
  12. }

Only this then I can map the template to the data like this:

  1. &lt;img src=&quot;{{ .picture }}&quot;&gt;
  2. &lt;p&gt;Hello, {{ .nickname }}&lt;/p&gt;

I'm quite sure it's necessary to set the template data. I'm just not sure why the above doc didn't do that.

Any help would be appreciated.

答案1

得分: 1

我刚刚尝试运行了Beego快速入门项目,并成功运行了它。

请确保已安装beegobee。在使用bee new projectname创建新项目后,确保编辑projectname/conf/app.conf文件并添加sessionon = true

  1. appname = quickstart
  2. httpport = 8080
  3. runmode = dev
  4. sessionon = true

我创建了一个重定向控制器:

  1. type RedirectController struct {
  2. beego.Controller
  3. }
  4. func (c *RedirectController) Get() {
  5. profile := make(map[string]interface{})
  6. profile["nickname"] = "用户的昵称"
  7. profile["picture"] = "/path/to/img.jpg"
  8. c.SetSession("profile", profile)
  9. c.Redirect("/", 301)
  10. }

主控制器:

  1. type MainController struct {
  2. beego.Controller
  3. }
  4. func (c *MainController) Get() {
  5. profile := c.GetSession("profile")
  6. c.Data["nickname"] = profile.(map[string]interface{})["nickname"]
  7. c.Data["picture"] = profile.(map[string]interface{})["picture"]
  8. c.TplNames = "index.tpl"
  9. }

我的index.tpl文件:

  1. <p>昵称:{{.nickname}}</p>
  2. <p>图片:{{.picture}}</p>

以及路由器:

  1. func init() {
  2. beego.Router("/", &controllers.MainController{})
  3. beego.Router("/redirect", &controllers.RedirectController{})
  4. }

我还建议您使用一个结构体来存储配置文件的值,例如:

  1. // 定义结构体。
  2. type Profile struct{
  3. Nickname string
  4. Picture string
  5. }
  6. // 保存用于模板渲染。
  7. this.Data["profile"] = &Profile{Nickname:"astaxie", Picture:"img.jpg"}
  8. // 并像这样渲染它:
  9. 昵称:{{.profile.Nickname}}
  10. 图片:{{.profile.Picture}}

请确保阅读这个以了解如何进行模板渲染。希望这就是您所询问的内容,如果不是,请编辑您的问题并添加更多有用的信息,我将编辑此答案。

英文:

I just tried running the Beego quickstart project and ran it successfully.

Make sure you have both the beego and bee installed. After creating a new project with bee new projectname make sure you edit the projectname/conf/app.conf file and add the sessionon = true:

  1. appname = quickstart
  2. httpport = 8080
  3. runmode = dev
  4. sessionon = true

I created a redirect controller like:

  1. type RedirectController struct {
  2. beego.Controller
  3. }
  4. func (c *RedirectController) Get() {
  5. profile := make(map[string]interface{})
  6. profile[&quot;nickname&quot;] = &quot;User&#39;s Nickname&quot;
  7. profile[&quot;picture&quot;] = &quot;/path/to/img.jpg&quot;
  8. c.SetSession(&quot;profile&quot;, profile)
  9. c.Redirect(&quot;/&quot;, 301)
  10. }

The main controller:

  1. type MainController struct {
  2. beego.Controller
  3. }
  4. func (c *MainController) Get() {
  5. profile := c.GetSession(&quot;profile&quot;)
  6. c.Data[&quot;nickname&quot;] = profile.(map[string]interface{})[&quot;nickname&quot;]
  7. c.Data[&quot;picture&quot;] = profile.(map[string]interface{})[&quot;picture&quot;]
  8. c.TplNames = &quot;index.tpl&quot;
  9. }

My index.tpl file:

  1. &lt;p&gt;Nickname: {{.nickname}}&lt;/p&gt;
  2. &lt;p&gt;Picture: {{.picture}}&lt;/p&gt;

And the router:

  1. func init() {
  2. beego.Router(&quot;/&quot;, &amp;controllers.MainController{})
  3. beego.Router(&quot;/redirect&quot;, &amp;controllers.RedirectController{})
  4. }

I would also recommend you to use a structure to store the profile values like:

  1. // Define struct.
  2. type Profile struct{
  3. Nickname string
  4. Picture string
  5. }
  6. // Save it for template rendering.
  7. this.Data[&quot;profile&quot;] = &amp;Profile{Nickname:&quot;astaxie&quot;, Picture:&quot;img.jpg&quot;}
  8. // And render it like this:
  9. Nickname: {{.profile.Nickname}}
  10. Picture: {{.profile.Picture}}

Make sure to read this to understand how template rendering is done. I hope this is what you were asking for, if not, please edit your question and add more helpful information and I will edit this answer.

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

发表评论

匿名网友

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

确定