在上节课内容中,我们学习实现了写文章的功能。本节课,我们要实现首页功能的开发。首页是用户登录后要展示的页面。最终想实现的功能是:点击首页,就会自动查询数据库,显示文章;如果文章较多,我们可以实现分页。
一、查询文章功能
1.1 Controller
我们首先修改home_controller.go文件,在Get()方法中,先查询所有的文章,并显示到页面上。因为文章可能很多,为了更好的用户体验,我们需要分页查询。默认查询第一页。
func (this *HomeController) Get() {
page, _ := this.GetInt("page")
if page <= 0 {
page = 1
}
var artList []models.Article
artList, _ = models.FindArticleWithPage(page)
this.Data["PageCode"] = 1
this.Data["HasFooter"] = true
fmt.Println("IsLogin:", this.IsLogin, this.Loginuser)
this.Data["Content"] = models.MakeHomeBlocks(artList, this.IsLogin)
this.TplName = "home.html"
}
1.2 Model
我们现在article_model.go文件中,添加文章的查询,而且要分页查询:
//-----------查询文章---------
//根据页码查询文章
func FindArticleWithPage(page int) ([]Article, error) {
//从配置文件中获取每页的文章数量
num, _ := beego.AppConfig.Int("articleListPageNum")
page--
fmt.Println("---------->page", page)
return QueryArticleWithPage(page, num)
}
/**
分页查询数据库
limit分页查询语句,
语法:limit m,n
m代表从多少位开始获取,与id值无关
n代表获取多少条数据
注意limit前面咩有where
*/
func QueryArticleWithPage(page, num int) ([]Article, error) {
sql := fmt.Sprintf("limit %d,%d", page*num, num)
return QueryArticlesWithCon(sql)
}
func QueryArticlesWithCon(sql string) ([]Article, error) {
sql = "select id,title,tags,short,content,author,createtime from article " + sql
rows, err := utils.QueryDB(sql)
if err != nil {
return nil, err
}
var artList []Article
for rows.Next() {
id := 0
title := ""
tags := ""
short := ""
content := ""
author := ""
var createtime int64
createtime = 0
rows.Scan(&id, &title, &tags, &short, &content, &author, &createtime)
art := Article{id, title, tags, short, content, author, createtime}
artList = append(artList, art)
}
return artList, nil
}
在models目录下创建一个go文件,用来控制首页显示内容:
type HomeBlockParam struct {
Id int
Title string
Tags [] TagLink
Short string
Content string
Author string
CreateTime string
//查看文章的地址
Link string
//修改文章的地址
UpdateLink string
DeleteLink string
//记录是否登录
IsLogin bool
}
type TagLink struct {
TagName string
TagUrl string
}
我们需要将从数据库中查询出来的数据,转为对应的结构体对象,所以先设计结构体,这里我们需要考虑如果用户是登录状态,那么是可以修改或删除某一篇文章。当然,如果没有登录,那么只能查看。所以在设计结构体的时候,我们直接创建了修改和删除的链接字段。
接下来,我们添加一个方法,用于将文章中的内容,显示到页面上:
//----------首页显示内容---------
func MakeHomeBlocks(articles []Article, isLogin bool) template.HTML {
htmlHome := ""
for _, art := range articles {
//将数据库model转换为首页模板所需要的model
homeParam := HomeBlockParam{}
homeParam.Id = art.Id
homeParam.Title = art.Title
homeParam.Tags = createTagsLinks(art.Tags)
fmt.Println("tag-->", art.Tags)
homeParam.Short = art.Short
homeParam.Content = art.Content
homeParam.Author = art.Author
homeParam.CreateTime = utils.SwitchTimeStampToData(art.Createtime)
homeParam.Link = "/article/" + strconv.Itoa(art.Id)
homeParam.UpdateLink = "/article/update?id=" + strconv.Itoa(art.Id)
homeParam.DeleteLink = "/article/delete?id=" + strconv.Itoa(art.Id)
homeParam.IsLogin = isLogin
//处理变量
//ParseFile解析该文件,用于插入变量
t, _ := template.ParseFiles("views/block/home_block.html")
buffer := bytes.Buffer{}
//就是将html文件里面的比那两替换为穿进去的数据
t.Execute(&buffer, homeParam)
htmlHome += buffer.String()
}
fmt.Println("htmlHome-->",htmlHome)
return template.HTML(htmlHome)
}
额外还需要一个方法:
//将tags字符串转化成首页模板所需要的数据结构
func createTagsLinks(tags string) []TagLink {
var tagLink [] TagLink
tagsPamar := strings.Split(tags, "&")
for _, tag := range tagsPamar {
tagLink = append(tagLink, TagLink{tag, "/?tag=" + tag})
}
return tagLink
}
1.3 View
接下来我们设计一下页面,刚刚在model的MakeHomeBlocks()方法中,就是需要使用模板填充格式化html页面内容,所以我们在views/block下再创建一个html页面:home_block.html,内容如下:
<div id="home-block-item">
<h2><a href="{{.Link}}">{{.Title}}</a></h2>
<div>
<span>{{.CreateTime}}</span>
<span>
{{range .Tags}}
<a href="{{.TagUrl}}"> {{.TagName}}</a>
{{end}}
</span>
</div>
<p><a href={{.Link}}>{{.Short}}</a></p>
{{if .IsLogin}}
<div class="home-block-item-udpate">
<a href='javascript:if(confirm("确定删除吗?")){location="{{.DeleteLink}}"}'>删除</a>
<a href={{.UpdateLink}}>修改</a>
</div>
{{end}}
</div>
我们现实了从数据中查询出的文章的数据,如果用户是登录状态,那么我们现实删除和修改,因为用户有这两个权限,否则就不显示。
1.4 运行
我们在数据库中插入10条数据:
接下来我们设置一下配置文件,每页显示6条(也可以8条,10条。。),
修改conf目录下的app.conf文件:
appname = myblog
httpport = 8080
runmode = dev
#mysql配置
driverName = mysql
mysqluser = root
mysqlpwd = yu271400
host = 127.0.0.1
port = 3306
dbname = myblog
#Session
sessionon = true
sessionprovider = "file"
sessionname = "qianfengjiaoyumyblog"
sessiongcmaxlifetime = 1800
sessionproviderconfig = "./tmp"
sessioncookielifetime = 1800
articleListPageNum = 6
然后启动项目,打开浏览器输入网址:http://127.0.0.1:8080/
用户虽然没有登录,但是也是可以查看的,接下来我们点击登录按钮进行登录:
登录后,用户就可以有删除和修改的功能了。
二、分页功能
截止,我们已经已经能够显示出第一页的内容了,接下来我们添加上一页和下一页的功能。
2.1 Model
首先在home_model.go中添加一个分页的结构体对象:
type HomeFooterPageCode struct {
HasPre bool
HasNext bool
ShowPage string
PreLink string
NextLink string
}
接下来添加方法:
//-----------翻页-----------
//page是当前的页数
func ConfigHomeFooterPageCode(page int) HomeFooterPageCode {
pageCode := HomeFooterPageCode{}
//查询出总的条数
num := GetArticleRowsNum()
//从配置文件中读取每页显示的条数
pageRow, _ := beego.AppConfig.Int("articleListPageNum")
//计算出总页数
allPageNum := (num-1)/pageRow + 1
pageCode.ShowPage = fmt.Sprintf("%d/%d", page, allPageNum)
//当前页数小于等于1,那么上一页的按钮不能点击
if page <= 1 {
pageCode.HasPre = false
} else {
pageCode.HasPre = true
}
//当前页数大于等于总页数,那么下一页的按钮不能点击
if page >= allPageNum {
pageCode.HasNext = false
} else {
pageCode.HasNext = true
}
pageCode.PreLink = "/?page=" + strconv.Itoa(page-1)
pageCode.NextLink = "/?page=" + strconv.Itoa(page+1)
return pageCode
}
这段代码需要查询出数据库中所有文章的总量,所以我们要先在article_model.go文件中,加入查询总数据量的方法:
//------翻页------
//存储表的行数,只有自己可以更改,当文章新增或者删除时需要更新这个值
var artcileRowsNum = 0
//只有首次获取行数的时候采取统计表里的行数
func GetArticleRowsNum() int {
if artcileRowsNum == 0 {
artcileRowsNum = QueryArticleRowNum()
}
return artcileRowsNum
}
//查询文章的总条数
func QueryArticleRowNum() int {
row := utils.QueryRowDB("select count(id) from article")
num := 0
row.Scan(&num)
return num
}
我们还要考虑一个问题,就是当新增或删除文章的时候,数据总量会发生改变,所以还要修改增加文章的方法:
先新增一个方法用于设置总页数:
//设置页数
func SetArticleRowsNum(){
artcileRowsNum = QueryArticleRowNum()
}
然后修改增加文章的方法:
//---------添加文章-----------
func AddArticle(article Article) (int64, error) {
i, err := insertArticle(article)
SetArticleRowsNum()
return i, err
}
2.2 Controller
修改home_controller.go的Get()方法:
func (this *HomeController) Get() {
...
artList, _ = models.FindArticleWithPage(page)
this.Data["PageCode"] = models.ConfigHomeFooterPageCode(page)
this.Data["HasFooter"] = true
...
}
2.3 View
修改home.html页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<link href="../static/css/blogsheet.css" rel="stylesheet">
</head>
<body>
{{template "block/nav.html" .}}
<div id="main">
{{.Content}}
{{if .HasFooter}}
<div id="home-footer">
<a {{if .PageCode.HasPre}}href="{{.PageCode.PreLink}}" {{else}} class="disable" {{end}}>上一页</a>
<span>{{.PageCode.ShowPage}}页</span>
<a {{if .PageCode.HasNext}}href="{{.PageCode.NextLink}}" {{else}} class="disable" {{end}}>下一页</a>
</div>
{{end}}
</div>
</body>
</html>
增添上一页,下一页的链接。
2.4 运行
首先我们再向数据库中插入5条数据:
然后修改配置文件,每页显示5条。
接下来,我们新增加一篇文章,点击写博客:
最后一页显示为我们刚刚增加的一篇文章,截止到现在我们可以很完美的显示页码了。