iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 28
0
Modern Web

BeeGo系列 第 28

blog (2) - 前台呈現

今天來處理這幾個部份

  • 前台的呈現
    • 首頁,呈現最新的 10 篇文章,需要有分頁
    • 單篇文章

首頁

我們把原來的首頁替換掉,改為呈現最新的 10 篇文章,並且加上分頁。

所以打開 controllers/default.go ,修改裏面的 Get()

import (
  // 省略
  "github.com/astaxie/beego/utils/pagination"
}

func (c *MainController) Get() {
        var fields []string
        var sortby []string
        var order []string
        var query = make(map[string]string)

        sortby = []string{"PostedAt"}
        order = []string{"desc"}
        postsPerPage := 10
        postCount, err := models.CountPost()
        if err != nil {
        }
        paginator := pagination.SetPaginator(c.Ctx, postsPerPage, postCount)

        posts, err := models.GetAllPost(query, fields, sortby, order, int64(paginator.Offset()), int64(postsPerPage))
        if err != nil {
                logs.Error(err.Error())
        }
        c.Data["posts"] = posts
        /*
                post := posts[0].(models.Post)
                logs.Debug("1.", post.Title)
                logs.Debug("2.", post.Member.Username)
        */
        c.TplName = "index.tpl"
}

基本上就是呼叫 models/post.go 裡的 GetAllPost() 來取得指定頁次的 10 筆,比較特別的是使用了 pagination。

pagination.SetPaginator() 會幫我們從 Query parameter 裡取出跟頁次相關的資訊來處理分頁,產生 paginator 物件,後續就可以依據 paginator 物件的資訊來進行查詢,所以你會看到 GetAllPost() 的最後兩個參數直接就引用了 paginator.Offset() 以及 postsPerPage。

補充一下,這邊有增加一個 CountPost() 的函式,這是因為 pagination 會需要文章總數來計算分頁資訊。

// models/post.go
// 把 CountPost() 加到 models/post.go 最後
func CountPost() (id int64, err error) {
        o := orm.NewOrm()
        cnt, err := o.QueryTable(new(Post)).Count()
        if err != nil {
                logs.Error(err.Error())
        }
        // logs.Debug("Count(Post)=", cnt)
        return cnt, err
}

MainController.Get() 修改好以後,接下來是調整模版。

之前的模版全部不要了,改成使用之前改好的 base.tpl,並且加上文章的顯示與分頁的顯示。

{{ template "base.tpl" . }}

{{ define "content" }}
  <!-- 顯示文章 -->
  {{range $object := .posts}}
    <article>
      <h2><a href="{{urlfor "PostController.GetOne" ":id" $object.Id}}">{{$object.Title}}</a></h2>
      <div class="content border-top">
        {{str2html $object.Content}}
      </div>
      <div class="footer border-bottom text-right">
        {{$object.Member.Username}} at {{date $object.PostedAt "Y-m-d h:i:s"}}
      </div>
    </article>
  {{end}}

  {{if gt .paginator.PageNums 1}}
  <!-- 分頁的顯示 -->
  <nav aria-label="Page navigation">
  <ul class="pagination justify-content-end">
    {{if .paginator.HasPrev}}
        <li class="page-item"><a class="page-link" href="{{.paginator.PageLinkFirst}}">&lt;&lt;</a></li>
        <li class="page-item"><a class="page-link" href="{{.paginator.PageLinkPrev}}">&lt;</a></li>
    {{else}}
        <li class="page-item disabled"><a class="page-link">&lt;&lt;</a></li>
        <li class="page-item disabled"><a class="page-link">&lt;</a></li>
    {{end}}
    {{range $index, $page := .paginator.Pages}}
        <li{{if $.paginator.IsActive .}} class="page-item active"{{end}}>
            <a class="page-link" href="{{$.paginator.PageLink $page}}">{{$page}}</a>
        </li>
    {{end}}
    {{if .paginator.HasNext}}
        <li class="page-item"><a class="page-link" href="{{.paginator.PageLinkNext}}">&gt;</a></li>
        <li class="page-item"><a class="page-link" href="{{.paginator.PageLinkLast}}">&gt;&gt;</a></li>
    {{else}}
        <li class="page-item disabled"><a class="page-link">&gt;</a></li>
        <li class="page-item disabled"><a class="page-link">&gt;&gt;</a></li>
    {{end}}
  </ul>
  </nav>
  {{end}}

{{ end }}

單篇文章

接著是顯示單篇文章,讓我們增加一個 controller 來處理這件事情。

bee generate controller post

然後只改裏面的 GetOne()

func (c *PostController) GetOne() {
        idStr := c.Ctx.Input.Param(":id")
        id, _ := strconv.ParseInt(idStr, 0, 64)
        v, err := models.GetPostById(id)
        if err != nil {
                c.Data["notfound"] = true
        } else {
                c.Data["post"] = v
        }
        c.TplName = "post/detail.tpl"
}

本來是只輸出 JSON,拿掉 ServeJSON(),並加上 c.TplName = "post/detail.tpl" ,讓他輸出 HTML。

接著加上模版,模版內容很簡單,就只是顯示查詢到的文章。

{{ template "base.tpl" . }}

{{ define "content" }}
  <article>
    {{if .notfound }}
      <h1>Not found</h1>
        {{else}}
      <h1>{{.post.Title}}</h1>
      <div class="content">
            {{str2html .post.Content}}
      </div>
      <div class="footer border-bottom text-right">
        {{.post.Member.Username}} at {{date .post.PostedAt "Y-m-d h:i:s"}}
      </div>
        {{end}}
{{ end }}

{{ define "scripts" }}
{{ end }}

Controller 與模版都處理好以後,就來加 routing

// routers/router.go
func init() {
  // 略
  beego.Router("/post/:id", &controllers.PostController{}, "get:GetOne")
}

小結

好了,到這邊就已經處理完顯示的部份了,完整的程式碼可以參考 github day_28

下一篇就要來處理後台 - 寫文章的部份。


上一篇
blog (1) - 規劃與 model
下一篇
blog (3) - 後台管理
系列文
BeeGo30

尚未有邦友留言

立即登入留言