layui获得列表json数据_golang实战开发之博客功能篇:文章列表的读取与展示和分类筛选展示处理...

前面我们介绍了文章详情页面的展示的逻辑代码实现,这一节,我们将继续讲解文章列表的读取和展示、文章根据分类进行筛选、最新文章、热门文章等的调用处理逻辑。

首先,我们先编写文章列表页的前端代码。这里,我们文章采用类似WordPress博客的形式,直接将首页作为文章列表页面的展示。因此我们在template文件夹下创建index.html:

博客首页/文章列表html代码

{% include "partial/header.html" %}
<div class="layui-container index"><div class="layui-row layui-col-space15"><div class="layui-col-md8"><div class="layui-card"><div class="layui-card-body"><ul class="article-list">{% for item in articles %}<li class="item"><a href="/article/{{item.Id}}" class="link"><h5 class="title">{{item.Title}}</h5><div class="description">{{item.Description}}</div><div class="meta">{% if item.Category %}<span>{{item.Category.Title}}</span>{% endif %}<span>{{stampToDate(item.CreatedTime, "2006-01-02")}}</span><span>{{item.Views}} 阅读</span></div></a></li>{% endfor %}</ul></div>{% if prevPage || nextPage %}<div class="layui-card-body text-center"><div class="layui-box layui-laypage"><a href="{{prevPage}}" class="layui-laypage-prev{% if !prevPage %} layui-disabled{% endif %}">上一页</a><a href="{{nextPage}}" class="layui-laypage-next{% if !nextPage %} layui-disabled{% endif %}">下一页</a></div></div>{% endif %}</div></div><div class="layui-col-md4">{% include "partial/author.html" %}<div class="layui-card"><div class="layui-card-header">文章分类</div><div class="layui-card-body"><ul class="aside-list">{% for item in categories %}<li class="item"><a href="/?category_id={{item.Id}}" class="link"><h5 class="title">{{item.Title}}</h5></a></li>{% endfor %}</ul></div></div><div class="layui-card"><div class="layui-card-header">热门文章</div><div class="layui-card-body"><ul class="aside-list">{% for item in populars %}<li class="item"><a href="/article/{{item.Id}}" class="link"><h5 class="title">{{item.Title}}</h5><span class="extra">{{item.Views}}阅读</span></a></li>{% endfor %}</ul></div></div></div></div>
</div>
{% include "partial/footer.html" %}

列表页中,我们将页面分割成两栏,左边栏大约占2/3,右边栏大约占1/3。左边栏中为文章的列表、上下页信息。文章列表中,我们将展示包括文章标题、文章简介、文章分类、文章发布时间、文章浏览量等信息。右边栏中,用来展示分类列表、热门文章等内容。

左边显示的文章分类信息中,我们注意到显示文章分类使用的是{{item.Category.Title}},这是因为我们定义文章模型的时候,article.Category 它指向的是文章分类的模型,article.Category.Title 就能访问到文章分类的名称了。并且文章并不一定会存在分类,因此我们需要先判断分类是否存在{% if item.Category %}<span>{{item.Category.Title}}</span>{% endif %},即文章存在分类的时候,我们才输出分类信息。

同样,这里的文章发布时间,我们使用了{{stampToDate(article.CreatedTime, "2006-01-02")}}来显示。stampToDate是我们前面自定义的模板函数,它可以将时间戳按照给定的格式格式化输出。这里我们将文章发布的时间戳按照"2006-01-02"的格式来输出显示。

这里,我们还注意到,输出上下页信息的时候,先判断是否存在上下页{% if prevPage || nextPage %} ... {% endif %},只要上一页存在,或下一页存在,我们才输出上下页的标签,否则这一整块都不显示。当这一块显示的时候,如果没有上一页,则上一页按钮不可点击{% if !prevPage %} layui-disabled{% endif %},同样,没有下一页的时候,下一页按钮也不能点击{% if !nextPage %} layui-disabled{% endif %}

博客首页/文章列表控制器函数

文章博客首页/文章列表页面控制器我们写在controller/index.go index.go中修改IndexPage()函数:

func IndexPage(ctx iris.Context) {currentPage := ctx.URLParamIntDefault("page", 1)categoryId := uint(ctx.URLParamIntDefault("category_id", 0))//一页显示10条pageSize := 10//文章列表articles, total, _ := provider.GetArticleList(categoryId, "id desc", currentPage, pageSize)//读取列表的分类categories, _ := provider.GetCategories()for i, v := range articles {if v.CategoryId > 0 {for _, c := range categories {if c.Id == v.CategoryId {articles[i].Category = c}}}}//热门文章populars, _, _ := provider.GetArticleList(categoryId, "views desc", 1, 10)totalPage := math.Ceil(float64(total)/float64(pageSize))prevPage := ""nextPage := ""urlPfx := "/?"var category *model.Categoryif categoryId > 0 {urlPfx += fmt.Sprintf("category_id=%d&", categoryId)category, _ = provider.GetCategoryById(categoryId)}if currentPage > 1 {prevPage = fmt.Sprintf("%spage=%d", urlPfx, currentPage-1)}if currentPage < int(totalPage) {nextPage = fmt.Sprintf("%spage=%d", urlPfx, currentPage+1)}if currentPage == 2 {prevPage = strings.TrimRight(prevPage, "page=1")}ctx.ViewData("total", total)ctx.ViewData("articles", articles)ctx.ViewData("populars", populars)ctx.ViewData("totalPage", totalPage)ctx.ViewData("prevPage", prevPage)ctx.ViewData("nextPage", nextPage)ctx.ViewData("category", category)ctx.View("index.html")
}

在首页文章列表控制器中,我们需要从url中获取两个参数,一个是当前页面的页码currentPage := ctx.URLParamIntDefault("page", 1),另一个是当前页面的分类idcategoryId := uint(ctx.URLParamIntDefault("category_id", 0))。这里我们都是获取的int类型的数据,并且在没有获取到数据的时候,使用默认值来代替,因此我们使用了URLParamIntDefault方法。

我们每页显示10条,可以让列表页面差不多维持在2屏到2屏半左右的高度。pageSize := 10

接着就是读取根据条件读取文章列表了articles, total, _ := provider.GetArticleList(categoryId, "id desc", currentPage, pageSize)。我们在 provider/article.go 中,增加GetArticleList函数:

func GetArticleList(categoryId uint, order string, currentPage int, pageSize int) ([]*model.Article, int64, error) {var articles []*model.Articleoffset := (currentPage - 1) * pageSizevar total int64builder := config.DB.Model(model.Article{})if categoryId > 0 {builder = builder.Where("`category_id` = ?", categoryId)}if order != "" {builder = builder.Order(order)}if err := builder.Count(&total).Limit(pageSize).Offset(offset).Find(&articles).Error; err != nil {return nil, 0, err}return articles, total, nil
}

获取文章列表函数接收4个参数:

  • categoryId 是分类id,如果指定分类id,则只显示当前分类的文章列表。
  • order 是排序规则,传入order参数可以根据指定的字段规则进行排序,如id desc则表示按id倒序来显示。
  • currentPage 是当前读取的页数,这个参数一般由url参数中获取。
  • pageSize 是一页显示数量,这里我们默认显示10条。

这里面我们通过当前页码和每页显示数量来计算出mysql的offsetoffset := (currentPage - 1) * pageSize

再通过判断categoryId是否大于零来确定是否传入了分类id,如果有分类id,则添加分类id的条件builder = builder.Where("category_id= ?", categoryId)

如果传入了order排序规则,则添加order条件builder = builder.Order(order)

因为这是列表的展示,因此我们还需获取所有符合条件的文章数量,用来计算分页数量和分页展示信息var total int64

最后将文章列表、符合条件的文章数量、错误信息返回给控制器。

接着我们继续读取所有的分类,用来将分类赋值给文章列表中的文章:

categories, _ := provider.GetCategories()
for i, v := range articles {if v.CategoryId > 0 {for _, c := range categories {if c.Id == v.CategoryId {articles[i].Category = c}}}
}

同样地,我们需要获取所有分类,也需要在 provider/category.go 中添加GetCategories函数:

func GetCategories() ([]*model.Category, error) {var categories []*model.Categorydb := config.DBerr := db.Where("`status` = ?", 1).Find(&categories).Errorif err != nil {return nil, err}return categories, nil
}

我们只读取status = 1的分类,因为我们开始的时候,定义了status为1 表示正常的数据,status为0表示审核的数据,status为99表示已删除的数据。我们在处理数据的时候,不采取直接删除的方式,这么做是为了防止手误等各种意外操作,造成数据误删而没有恢复的机会。

首页列表中,我们在右边栏中,显示了热门文章。这里我们将浏览量最多的文章认为是热门文章。

populars, _, _ := provider.GetArticleList(categoryId, "views desc", 1, 10)

同样地,热门文章我们也使用GetArticleList函数来获取数据,我们只需要将排序规则views desc传入即可得到浏览量最多的文章。这里我们不需要读取分页,也不需要获取符合条件的数量,因此我们使用populars, _, _来接收数据,只保留文章列表,存入populars变量中,其他变量忽略,使用下划线_表示。

接着我们通过计算,算出是否有上一页、下一页,以及根据条件拼接上一页、下一页的连接。

prevPage := ""nextPage := ""urlPfx := "/?"var category *model.Categoryif categoryId > 0 {urlPfx += fmt.Sprintf("category_id=%d&", categoryId)category, _ = provider.GetCategoryById(categoryId)}if currentPage > 1 {prevPage = fmt.Sprintf("%spage=%d", urlPfx, currentPage-1)}if currentPage < int(totalPage) {nextPage = fmt.Sprintf("%spage=%d", urlPfx, currentPage+1)}if currentPage == 2 {prevPage = strings.TrimRight(prevPage, "page=1")}

最后,将页面需要使用的变量,都注入到view中,供前端使用,并指定前端页面模板:

ctx.ViewData("total", total)
ctx.ViewData("articles", articles)
ctx.ViewData("populars", populars)
ctx.ViewData("totalPage", totalPage)
ctx.ViewData("prevPage", prevPage)
ctx.ViewData("nextPage", nextPage)
ctx.ViewData("category", category)ctx.View("index.html")

配置首页文章列表页面路由

首页的路由,在一开始的时候,我们便已经配置过了,因此在这里我们不需要再次配置。它在route/route.go 中,我们给路由增加是否登录判断中间件:

app.Get("/", controller.Inspect, controller.IndexPage)

至此,我们的首页文章列表已经完成。我们的首页列表具有了分页功能,也能根据分类来筛选显示文章了。

验证结果

我们重启一下项目,我们先在浏览器中访问http://127.0.0.1:8001/来看看效果。如果不出意外可以看到这样的画面:

3a8b50325af6d04e7da88886345a8faf.png

教程用例源码

完整的项目示例代码托管在GitHub上,访问github.com/fesiong/goblog 可以查看完整的教程项目源代码,建议在查看教程的同时,认真对照源码,可以有效提高码代码速度和加深对博客项目的认识。建议直接fork一份来在上面做修改。欢迎点Star。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/523521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“智企云中享“,首届SAP中国云大会召开

2019 年 6 月 5 日&#xff0c;上海讯— 今日&#xff0c;首届SAP云大会在上海盛大召开。作为SAP云计算家族在中国的首秀&#xff0c;大会全面呈现了SAP云业务的战略、产品、商业场景、浸入式体验。作为体验管理领域的领导者&#xff0c;SAP以覆盖企业运营全价值链的云服务解决…

SpringBoot入门到精通_第7篇 _必知必会总结

接上一篇&#xff1a;SpringBoot入门到精通_第6篇 _必知必会

java对mysql读写权限设置_Java学习笔记——MySQL开放3306接口与设置用户权限

系统Ubuntu16.04 LTS1、开放3306端口查看端口状态:netstat -an|grep 3306tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN目前只有本机可以访问输入指令:sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf如果之前配置过全局配置文件,也可输入指令:su…

容器精华问答 | 如何进行跨机器的Container做Link ?

戳蓝字“CSDN云计算”关注我们哦&#xff01;云计算的发展日新月异&#xff0c;新技术层出不穷&#xff0c;尤其容器技术自2013年Docker容器问世以来一路高歌猛进红遍大江南北&#xff0c;与虚拟机相比&#xff0c;容器更显优势&#xff0c;有着更轻量、更快捷、占用资源更少&a…

Sublime Text3 多行合并为一行

快捷键说明CTRL J多行合并为一行ctrld双击选中关键词或者关键词部分&#xff0c;在输入快捷键关键字就会一个一个选中&#xff0c;就可以同时编辑

安卓psp模拟器哪个好_psp模拟器安卓完美版下载_psp模拟器完美版手机版下载_玩游戏网...

《psp模拟器完美版》App是专业的PSP游戏模拟器&#xff0c;兼容适配任何安卓机型&#xff0c;用户下载于此畅玩PSP游戏&#xff0c;还可自制游戏&#xff0c;能够自由设置多国语言&#xff0c;更改图像、声音、控制、网络等多种选项设置&#xff0c;想玩好游戏&#xff0c;玩打…

腾讯也有“神盾局”?秀出“技术肌肉”就靠TA了……

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;漫威的超级英雄世界中&#xff0c;“神盾局”一直凭借着不少的先进武器装备&#xff0…

Spring 集成 mybatisPlus

文章目录1. pom.xml2. 实体类3. mapper接口4. applicationContext.xml5. db.properties6. log4j.xml7. mybatis-config.xml8. 测试类9. 控制台输出10. 源码地址1. pom.xml <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://ma…

用python编excel统计表_Python实现对excel文件列表值进行统计的方法

本文实例讲述了Python实现对excel文件列表值进行统计的方法。分享给大家供大家参考。具体如下&#xff1a;#!/usr/bin/env python#codinggbk#此PY用来统计一个execl文件中的特定一列的值的分类import win32com.clientfilenameraw_input("请输入要统计文件的详细地址&#…

大话云存储,这个“对象”可能无处不在

戳蓝字“CSDN云计算”关注我们哦&#xff01;文 | pasca来源 | 蛋蛋团&#xff08;ID&#xff1a;dandan_tuan&#xff09;大纲前言1、Who&#xff1a;谁使用对象存储2、What&#xff1a;对象存储是什么3、Why&#xff1a;为什么他们会使用对象存储4、how to do:应用场景分析5、…

linux java文件 core_linux下部署.net core/java

.net core1.查看系统是否已安装net core命令&#xff1a;dotnet --info如果提示未找到命令&#xff0c;说明需要按照net core环境&#xff0c;否则跳过2&#xff0c;3两步2.查看系统版本&#xff0c;这里是CentOS 7命令&#xff1a;cat /etc/redhat-release3.根据系统版本找到安…

振奋!中国正式进入5G元年;华为5G俄罗斯签下大单;王坚进入工程院院士第二轮评审...

戳蓝字“CSDN云计算”关注我们哦&#xff01;嗨&#xff0c;大家好&#xff0c;重磅君带来的【云重磅】特别栏目&#xff0c;如期而至&#xff0c;每周五第一时间为大家带来重磅新闻。把握技术风向标&#xff0c;了解行业应用与实践&#xff0c;就交给我重磅君吧&#xff01;重…

java 对象复制 反射_利用Java反射机制实现对象相同字段的复制操作

一、如何实现不同类型对象之间的复制问题&#xff1f;1、为什么会有这个问题&#xff1f;近来在进行一个项目开发的时候&#xff0c;为了隐藏后端数据库表结构、同时也为了配合给前端一个更友好的API接口文档(swagger API文档)&#xff0c;我采用POJO来对应数据表结构&#xff…

企业实战_01_Redis下载/安装/运行/停止

文章目录一、Redis下载&#xff1a;官方&#xff1a;https://redis.io/二、Redis安装&#xff1a;2.1. 上传redis软件服务器2.2. 解压redis2.3. 进入redis目录&#xff0c;进行redis安装2.4. 执行redis安装测试&#xff1a;2.5. 安装异常处理三、redis 启动、停止3.1. 进入src目…

关于5G,你必须知道的事儿……

戳蓝字“CSDN云计算”关注我们哦&#xff01;文 | 小枣君来源 | 鲜枣课堂什么是5G 5G&#xff0c;就是5th Generation Mobile Networks&#xff08;第五代移动通信网络&#xff09;&#xff0c;也可以称为5th Generation Wireless Systems&#xff08;第五代无线通信系统&a…

java管理员登录_idea实现管理员登录javaweb

mysql创建db_0106数据库&#xff0c;创建表添加一条数据&#xff0c;id int自增&#xff0c;密码&#xff1a;为MD5加密insert into tb_sys values(null,admin,MD5(123),"系统管理员");项目目录结构com.isoft.db包下db.properties文件mysql.drivercom.mysql.jdbc.Dri…

linux环境下redis5.0的安装配置

文章目录一、Redis介绍&#xff1a;二、安装Redis2.1. 下载 解压 进入文件夹 然后 编译2.2. 启动Redis2.2.1. 指定配置文件启动redis2.2.2. 配置redis后台启动三. 登录验证一、Redis介绍&#xff1a; Redis是当前比较热门的NOSQL系统之一&#xff0c;它是一个key-value存储系统…

漫话:如何给女朋友解释什么是编译与反编译

戳蓝字“CSDN云计算”关注我们哦&#xff01;来源 | 漫话编程某天下班后&#xff0c;我在家里进行电话面试&#xff0c;问到面试者这样一个问题&#xff1a;"你知道使用哪些办法可以反编译Java代码吗&#xff1f;"。但是面试者回答的并不好&#xff0c;所以我在面试评…

java数组下标越界处理_可恶的Java数组下标越界检查

刚刚学习Java不到一个星期&#xff0c;本来是搞C的&#xff0c;没事学习Java&#xff0c;将来可以更好的想Android方向发展一下。现在正处于磨基础的阶段&#xff0c;对与每一个新手来书&#xff0c;最痛苦的莫过于此了。写了一个冒泡排序&#xff0c;用C的思想写&#xff0c;没…