### GoWeb开发实战Gin框架】微博项目实战-首页设计
# 首页设计
我们的想法是点击首页,就会自动查询数据库,显示文章。如果文章较多,我们可以实现分页。
## 一、查询文章功能
### 1.1 Controller
我们首先修改home\_controller.go文件,在Get()方法中,先查询所有的文章,并显示到页面上。因为文章可能很多,为了更好的用户体验,我们需要分页查询。默认查询第一页。
~~~go
func HomeGet(c *gin.Context) {
//获取session,判断用户是否登录
islogin := GetSession(c)
page := 1
var artList []models.Article
artList, _ = models.FindArticleWithPage(page)
html := models.MakeHomeBlocks(artList, islogin)
c.HTML(http.StatusOK, "home.html", gin.H{"IsLogin": islogin, "Content": html})
}
~~~
### 1.2 Model
先创建一个目录config,里面用来存储配置文件conf.go:
~~~go
package config
// 定义查询文章,每页显示的文章量
const NUM = 4
~~~
现在我们现在article\_model.go文件中,添加文章的查询,而且要分页查询:
~~~go
//-----------查询文章---------
//根据页码查询文章
func FindArticleWithPage(page int) ([]Article, error) {
page--
fmt.Println("---------->page", page)
//从配置文件中获取每页的文章数量
return QueryArticleWithPage(page, config.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 := database.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文件,用来控制首页显示内容:
~~~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
}
~~~
我们需要将从数据库中查询出来的数据,转为对应的结构体对象,所以先设计结构体,这里我们需要考虑如果用户是登录状态,那么是可以修改或删除某一篇文章。当然,如果没有登录,那么只能查看。所以在设计结构体的时候,我们直接创建了修改和删除的链接字段。
接下来,我们添加一个方法,用于将文章中的内容,显示到页面上:
~~~go
//----------首页显示内容---------
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 = "/show/" + 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/home_block.html")
buffer := bytes.Buffer{}
//就是将html文件里面的比那两替换为穿进去的数据
t.Execute(&buffer, homeParam)
htmlHome += buffer.String()
}
fmt.Println("htmlHome-->",htmlHome)
return template.HTML(htmlHome)
}
~~~
额外还需要一个方法:
~~~go
//将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目录下再创建一个html页面:home\_block.html,内容如下:
~~~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条。。),
修改config目录下的conf.go文件:
~~~go
package config
// 定义查询文章,每页显示的文章量
const NUM = 6
~~~
然后启动项目,打开浏览器输入网址:[http://127.0.0.1:8081/](http://127.0.0.1:8081/)

用户虽然没有登录,但是也是可以查看的,接下来我们点击登录按钮进行登录:

登录后,用户就可以有删除和修改的功能了。
## 二、分页功能
截止,我们已经已经能够显示出第一页的内容了,接下来我们添加上一页和下一页的功能。
### 2.1 Model
首先在home\_model.go中添加一个分页的结构体对象:
~~~go
type HomeFooterPageCode struct {
HasPre bool
HasNext bool
ShowPage string
PreLink string
NextLink string
}
~~~
接下来添加方法:
~~~go
//-----------翻页-----------
//page是当前的页数
func ConfigHomeFooterPageCode(page int) HomeFooterPageCode {
pageCode := HomeFooterPageCode{}
//查询出总的条数
num := GetArticleRowsNum()
//计算出总页数
allPageNum := (num-1)/config.NUM + 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文件中,加入查询总数据量的方法:
~~~go
//------翻页------
//存储表的行数,只有自己可以更改,当文章新增或者删除时需要更新这个值
var artcileRowsNum = 0
//只有首次获取行数的时候采取统计表里的行数
func GetArticleRowsNum() int {
if artcileRowsNum == 0 {
artcileRowsNum = QueryArticleRowNum()
}
return artcileRowsNum
}
//查询文章的总条数
func QueryArticleRowNum() int {
row := database.QueryRowDB("select count(id) from article")
num := 0
row.Scan(&num)
return num
}
~~~
我们还要考虑一个问题,就是当新增或删除文章的时候,数据总量会发生改变,所以还要修改增加文章的方法:
先新增一个方法用于设置总页数:
~~~go
//设置页数
func SetArticleRowsNum(){
artcileRowsNum = QueryArticleRowNum()
}
~~~
然后修改增加文章的方法:
~~~go
//---------添加文章-----------
func AddArticle(article Article) (int64, error) {
i, err := insertArticle(article)
SetArticleRowsNum()
return i, err
}
~~~
### 2.2 Controller
修改home\_controller.go的Get()方法:
~~~go
func (this *HomeController) Get() {
...
page, _ := strconv.Atoi(c.Query("page"))
if page <= 0 {
page = 1
}
...
homeFooterPageCode:=models.ConfigHomeFooterPageCode(page)
c.HTML(http.StatusOK, "home.html", gin.H{"IsLogin": islogin, "Content": html,"HasFooter":true,"PageCode":homeFooterPageCode})
...
}
~~~
### 2.3 View
修改home.html页面:
~~~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条。

接下来,我们新增加一篇文章,点击写博客:

在添加标签的时候,通过&区分多个标签。然后点击提交按钮。

最后一页显示为我们刚刚增加的一篇文章,截止到现在我们可以很完美的显示页码了。