第009节:首页设计

                           

在上节课内容中,我们学习实现了写文章的功能。本节课,我们要实现首页功能的开发。首页是用户登录后要展示的页面。最终想实现的功能是:点击首页,就会自动查询数据库,显示文章;如果文章较多,我们可以实现分页。

一、查询文章功能

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,内容如下:

{{.Title}}

{{.CreateTime}} {{range .Tags}}  {{.TagName}} {{end}}

{{.Short}}

{{if .IsLogin}} {{end}}

我们现实了从数据中查询出的文章的数据,如果用户是登录状态,那么我们现实删除和修改,因为用户有这两个权限,否则就不显示。

1.4 运行

我们在数据库中插入10条数据:
http://7xtcwd.com1.z0.glb.clouddn.com/WX20190522-113706@2x.png

接下来我们设置一下配置文件,每页显示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/

http://7xtcwd.com1.z0.glb.clouddn.com/WX20190522-141320@2x.png

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

http://7xtcwd.com1.z0.glb.clouddn.com/WX20190522-141446@2x.png

登录后,用户就可以有删除和修改的功能了。

二、分页功能

截止,我们已经已经能够显示出第一页的内容了,接下来我们添加上一页和下一页的功能。

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页面:




    
    首页
    


{{template "block/nav.html" .}}

{{.Content}} {{if .HasFooter}} {{end}}

增添上一页,下一页的链接。

2.4 运行

首先我们再向数据库中插入5条数据:

http://7xtcwd.com1.z0.glb.clouddn.com/WX20190522-141654@2x.png

然后修改配置文件,每页显示5条。

http://7xtcwd.com1.z0.glb.clouddn.com/WX20190522-141839@2x.png

接下来,我们新增加一篇文章,点击写博客:
http://7xtcwd.com1.z0.glb.clouddn.com/WX20190522-142111@2x.png

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

原创文章,Golang中国出品,文章对应源码下载:https://www.qfgolang.com/?page_id=1973

发表评论

电子邮件地址不会被公开。 必填项已用*标注

联系我们

学习交流群:点击这里给我发消息

QR code