今天來處理這幾個部份
我們把原來的首頁替換掉,改為呈現最新的 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}}"><<</a></li>
<li class="page-item"><a class="page-link" href="{{.paginator.PageLinkPrev}}"><</a></li>
{{else}}
<li class="page-item disabled"><a class="page-link"><<</a></li>
<li class="page-item disabled"><a class="page-link"><</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}}">></a></li>
<li class="page-item"><a class="page-link" href="{{.paginator.PageLinkLast}}">>></a></li>
{{else}}
<li class="page-item disabled"><a class="page-link">></a></li>
<li class="page-item disabled"><a class="page-link">>></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。
下一篇就要來處理後台 - 寫文章的部份。