配置清除缓存
当进入前台首页时,会缓存对应的商品相关数据,这时,如果后台修改了商品的相关数据,缓存中的对应数据并没有随之发生改变,这时就需要需改对应的缓存数据,这里有两种方法:
方法一
在管理后台操作直接清除缓存中的所有数据,当再次访问前台首页时,就会先从数据库中获取数据,然后缓存到redis中,代码如下:
(1).界面
点击 清除缓存 按钮,直接清除缓存驱动中的所有数据
(2).增加 清除缓存 按钮
在templates/admin/main/index.html页面,增加 清除缓存 按钮
<ul class="nav navbar-nav navbar-right">
<li><a>欢迎您,{{.username}}</a>
</li>
<li><a href="/admin/flushAll">清除缓存</a>
<li><a href="/admin/loginOut">安全退出</a>
</li>
</ul>
(3).增加路由
在routers/admin/adminRouter.go中增加 清除缓存 路由
adminRouters.GET("/flushAll", admin.MainController{}.FlushAll)
(4).增加清除缓存方法
在controllers/admin/MainController.go中增加清除缓存的方法
//清除缓存
func (con MainController) FlushAll(c *gin.Context) {
models.RedisCache.FlushAll()
con.Success(c, "清除缓存成功", "/admin")
}
在models /redisCache.go中增加清除缓存方法
//清除缓存
func (r RedisCache) FlushAll() {
if redisEnable {
RedisDb.FlushAll(ctxRedis)
}
}
方法二
在管理后台修改商品相关数据时,就去修改对应的缓存数据,代码:略
2.分类页面数据展示
当从首页点击 商品分类,进入商品分类的 商品展示页面时,会存在和首页共同的 公共数据( 顶部导航、中间导航、左侧分类),那么就可以把公共的代码分离出来,放到 基础控制器(BaseController.go)中,实现 代码的复用;
在商品分类的商品展示页面 展示分类的对应商品,以及 筛选对应分类的商品,和对商品进行 分页操作
1).界面
首页界面
商品分类对应的商品页面: 该页面和首页都有共同的 公共数据( 顶部导航、中间导航、左侧分类)
商品列表
2).代码展示
(1).html
拆分publibc/page_header.html,把中部导航代码单独成一个文件middle_nav.html
index.html中增加 中部导航 代码
创建product/list.html商品页面文件
page_header.html
拆分publibc/page_header.html,把中部导航代码单独成一个文件middle_nav.html
<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "frontend/public/page_header.html" }}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="author" content="order by dede58.com"/>
<title>小米商城</title>
<link rel="stylesheet" type="text/css" href="/static/frontend/css/style.css">
<link rel="stylesheet" href="/static/frontend/css/swiper.min.css">
<script src="/static/frontend/js/jquery-1.10.1.js"></script>
<script src="/static/frontend/js/swiper.min.js"></script>
<script src="/static/frontend/js/base.js"> </script>
</head>
<body>
<!-- start header 顶部导航 -->
<header>
<div class="top center">
<div class="left fl">
<ul>
<!--获取长度,并计算,看看是否显示最后的 | 画线-->
{{ $temp := .topNavList | len }}
{{ $navLen := Sub $temp 1 }}
{{range $key, $value := .topNavList}}
<li><a href="{{$value.Link}}"{{if eq $value.IsOpennew 1 }} target="_blank" {{end}} >{{$value.Title}}</a></li>
{{if lt $key $navLen}}
<li>|</li>
{{end}}
{{end}}
<div class="clear"></div>
</ul>
</div>
<div class="right fr">
<div class="gouwuche fr"><a href="">购物车</a></div>
<div class="fr">
<ul>
<li><a href="./login.html" target="_blank">登录</a></li>
<li>|</li>
<li><a href="./register.html" target="_blank" >注册</a></li>
<li>|</li>
<li><a href="">消息通知</a></li>
</ul>
</div>
<div class="clear"></div>
</div>
<div class="clear"></div>
</div>
</header>
<!--end header -->
{{end}}
list.html
创建product/list.html商品页面文件
{{ define "frontend/public/middle_nav.html" }}
<!-- 中间导航start banner_x -->
<div class="banner_x center">
<a href="/" target="_blank">
<div class="logo fl"></div>
</a>
<div class="nav fl">
<ul class="clearfix" id="nav_list">
<li class="link-category">
<a href="#">全部商品分类</a>
<div class="banner_y center">
<div class="nav">
<ul>
{{range $key,$value := .goodsCateList}}
<li>
<!--判断点击分类是否跳转到一个新的链接,如果不是,则跳转到对应的分类商品页面-->
{{if eq $value.Link ""}}
<a href="category{{$value.Id}}" target="_blank">{{$value.Title}}</a>
{{else}}
<a href="{{$value.Link}}" target="_blank">{{$value.Title}}</a>
{{end}}
<div class="pop">
<ol class="cate_list clear">
{{range $k,$v := $value.GoodsCateItems}}
<li>
<div class="xuangou_left">
{{if eq $v.Link ""}}
<a href="category{{$v.Id}}" target="_blank"
class="clearfix">
<div class="img fl"><img
src="{{$v.CateImg | FormatImg}}"
alt="{{$v.Title}}"></div>
<span class="fl">{{$v.Title}}</span>
</a>
{{else}}
<a href="{{$v.Link}}" target="_blank" class="clearfix">
<div class="img fl"><img
src="{{$v.CateImg | FormatImg}}"
alt="{{$v.Title}}"></div>
<span class="fl">{{$v.Title}}</span>
</a>
{{end}}
</div>
</li>
{{end}}
</ol>
</div>
</li>
{{end}}
</ul>
</div>
</div>
</li>
{{range $key,$value := .middleNavList}}
<li>
<a href="#" target="_blank">{{$value.Title}}</a>
<ol class="children-list clearfix">
{{range $k,$v := $value.GoodsItems}}
<li>
<a href="#">
<img src="{{$v.GoodsImg | FormatImg}}" alt="{{$v.Title}}"/>
<p>{{$v.Price}}元</p>
</a>
</li>
{{end}}
</ol>
</li>
{{end}}
</ul>
</div>
<div class="search fr">
<form action="" method="post">
<div class="text fl">
<input type="text" class="shuru" placeholder="6 MIX现货">
</div>
<div class="submit fl">
<input type="submit" class="sousuo" value="搜索"/>
</div>
<div class="clear"></div>
</form>
<div class="clear"></div>
</div>
</div>
<!-- end banner_x -->
{{end}}
index.html
商品首页增加 中部导航 代码, 因为page_header.html中的中部导航代码没有了,已经封装成middle_nav.html代码了,而首页的商品分类和商品页面的商品分类还有点区别,故不会导入public/middle_nav.html中的代码,所以会直接增加 中部导航 代码
{{ define "frontend/index/index.html" }}
{{template "frontend/public/page_header.html" .}}
<!-- start banner_x 中部导航 -->
<div class="banner_x center">
<a href="./index.html" target="_blank"><div class="logo fl"></div></a>
<a href=""><div class="ad_top fl"></div></a>
<div class="nav fl">
<ul class="clearfix" id="nav_list">
{{range $key, $value := .middleNavList }}
<li>
<a href="{{$value.Link}}" target="_blank">{{$value.Title}}</a>
<ol class="children-list clearfix">
{{range $k, $v := $value.GoodsItems }}
<li>
<a href="#">
<img src="{{$v.GoodsImg | FormatImg }}" />
<p>{{$v.Price}}</p>
</a>
</li>
{{end}}
</ol>
</li>
{{end}}
</ul>
</div>
<div class="search fr">
<form action="" method="post">
<div class="text fl">
<input type="text" class="shuru" placeholder="小米6 小米MIX现货">
</div>
<div class="submit fl">
<input type="submit" class="sousuo" value="搜索"/>
</div>
<div class="clear"></div>
</form>
<div class="clear"></div>
</div>
</div>
<!-- end banner_x -->
<!-- 商品分类 start banner_y -->
<div class="banner_y center">
<div class="nav">
<ul>
{{range $key, $value := .goodsCateList }}
<li>
{{if eq $value.Link ""}}
<a href="category{{$value.Id}}" target="_blank">{{$value.Title}}</a>
{{else}}
<a href="{{$value.Link}}" target="_blank">{{$value.Title}}</a>
{{end}}
<div class="pop">
<ol class="cate_list clear">
{{range $k, $v := $value.GoodsCateItems}}
<li>
<div class="xuangou_left">
{{if eq $v.Link ""}}
<a href="category{{$v.Id}}" target="_blank"
class="clearfix">
<div class="img fl"><img
src="{{$v.CateImg | FormatImg}}"
alt="{{$v.Title}}"></div>
<span class="fl">{{$v.Title}}</span>
</a>
{{else}}
<a href="{{$v.Link}}" target="_blank" class="clearfix">
<div class="img fl"><img
src="{{$v.CateImg | FormatImg}}"
alt="{{$v.Title}}"></div>
<span class="fl">{{$v.Title}}</span>
</a>
{{end}}
</div>
</li>
{{end}}
</ol>
</div>
</li>
{{end}}
</ul>
</div>
<!--轮播图-->
<div class="swiper-container">
<div class="swiper-wrapper">
{{range $key, $value := .focusList}}
<div class="swiper-slide">
<a href="{{$value.Link}}" target="_blank">
<img src="{{$value.FocusImg | FormatImg}}" alt="{{$value.Title}}" />
</a>
</div>
{{end}}
</div>
<!-- Add Arrows -->
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
</div>
</div>
<!-- 商品分类end -->
<div class="sub_banner center">
<div class="sidebar fl">
<div class="fl"><a href=""><img src="/static/frontend/image/hjh_01.gif"></a></div>
<div class="fl"><a href=""><img src="/static/frontend/image/hjh_02.gif"></a></div>
<div class="fl"><a href=""><img src="/static/frontend/image/hjh_03.gif"></a></div>
<div class="fl"><a href=""><img src="/static/frontend/image/hjh_04.gif"></a></div>
<div class="fl"><a href=""><img src="/static/frontend/image/hjh_05.gif"></a></div>
<div class="fl"><a href=""><img src="/static/frontend/image/hjh_06.gif"></a></div>
<div class="clear"></div>
</div>
<div class="datu fl"><a href=""><img src="/static/frontend/image/hongmi4x.png" alt=""></a></div>
<div class="datu fl"><a href=""><img src="/static/frontend/image/xiaomi5.jpg" alt=""></a></div>
<div class="datu fr"><a href=""><img src="/static/frontend/image/pinghengche.jpg" alt=""></a></div>
<div class="clear"></div>
</div>
<!-- end banner -->
<!-- 手机 -->
<div class="category_item w">
<div class="title center">手机</div>
<div class="main center">
<div class="category_item_left">
<img src="static/itying/image/shouji.jpg" alt="手机">
</div>
<div class="category_item_right">
{{range $key,$value := .phoneList}}
<div class="hot fl">
<div class="xinpin"><span style="background:#fff"></span></div>
<div class="tu"><a href="#"><img src="{{$value.GoodsImg | FormatImg}}"></a></div>
<div class="miaoshu"><a href="#">{{$value.Title}}</a></div>
<div class="jiage">{{$value.Price}}元</div>
<div class="pingjia">372人评价</div>
<div class="piao">
<a href="">
<span>{{SubStr $value.SubTitle 0 4}}</span>
</a>
</div>
</div>
{{end}}
</div>
</div>
</div>
{{template "frontend/public/page_footer.html" .}}
</body>
</html>
{{end}}
(2).增加商品分类页面路由
defaultRouters.GET("/category:id", frontend.ProductController{}.Category)
(3).基础控制器
在基础控制器BaseController.go中创建公共方法: 加载公共模板方法Render()
package frontend
//基础控制器
import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"goshop/models"
"net/http"
"strings"
)
type BaseController struct{}
/*
加载公共模板方法
tpl string 模板
data map 请求的数据
*/
func (con BaseController) Render(c *gin.Context, tpl string, data map[string]interface{}) {
//实例化redisCache结构体
redisCache := models.RedisCache{}
//获取顶部导航列表
topNavList := []models.Nav{}
//判断redis中是否存在数据
if hasTopNavList := redisCache.Get("topNavList", &topNavList); !hasTopNavList { //不存在数据,则从数据中获取数据,并把数据保存到redis
models.DB.Where("status = 1 AND position = 1").Find(&topNavList)
redisCache.Set("topNavList", topNavList, 3600)
}
//获取分类数据
goodsCateList := []models.GoodsCate{}
if hasGoodsCateList := redisCache.Get("goodsCateList", &goodsCateList); !hasGoodsCateList {
//获取分类列表以及下级分类,并进行排序
models.DB.Where("pid = ? AND status = ?", 0, 1).Order("sort DESC").Preload("GoodsCateItems", func(db *gorm.DB) *gorm.DB {
return db.Where("goods_cate.status = 1").Order("goods_cate.sort DESC")
} ).Find(&goodsCateList)
redisCache.Set("goodsCateList", goodsCateList, 3600)
}
//获取中间导航
middleNavList := []models.Nav{}
if hasMiddleNavList := redisCache.Get("middleNavList", &middleNavList); !hasMiddleNavList {
models.DB.Where("status = ? AND position = ? ", 1, 2).Find(&middleNavList)
//循环,获取中间导航对应的商品数据
for i:= 0; i < len(middleNavList);i++{
//获取管理商品
//替换字符串中的中文逗号strings.ReplaceAll()
relation := strings.ReplaceAll(middleNavList[i].Relation, ",", ",")
//把字符串转换成切片
relationIds := strings.Split(relation, ",")
//获取对应的商品信息
goodsList := []models.Goods{}
models.DB.Where("status = ?", 1).Where("id in ?", relationIds).Select("id, title, goods_img, price").Find(&goodsList)
middleNavList[i].GoodsItems = goodsList
}
redisCache.Set("middleNavList", middleNavList, 3600)
}
renderData := gin.H{
"topNavList": topNavList,
"goodsCateList": goodsCateList,
"middleNavList": middleNavList,
}
for key, v := range data {
renderData[key] = v
}
c.HTML(http.StatusOK, tpl, renderData)
}
(4).商品控制器
创建ProductController.go控制器,该控制器与商品相关
package frontend
//商品相关
import (
"github.com/gin-gonic/gin"
"goshop/models"
"math"
)
type ProductController struct {
//extend 基础控制器
BaseController
}
// 根据商品分类获取分类下面的所有商品数据
func (con ProductController) Category(c *gin.Context) {
//获取分类id
cateId, _ := models.Int(c.Param("id"))
//当前页
page, _ := models.Int(c.Query("page"))
if page == 0 {
page = 1
}
//每一页显示的数量
pageSize := 2
//获取当前分类
curCate := models.GoodsCate{}
models.DB.Where("id = ? ", cateId).Find(&curCate)
//判断当前分类是否顶级分类,如果是,则获取对应的二级分类,如果不是,则获取对应的兄弟分类
subCate := []models.GoodsCate{}
var tempSlice []int
if curCate.Pid == 0 { // 当前分类是顶级分类,获取对应的二级分类
models.DB.Where("pid = ?", cateId).Find(&subCate)
//把二级分类id放到切片中
for i := 0; i < len(subCate); i++ {
tempSlice = append(tempSlice, subCate[i].Id)
}
} else { // 当前分类是二级分类,获取对应的兄弟分类
models.DB.Where("pid = ?", curCate.Pid).Find(&subCate)
}
//把请求的分类id放入切片
tempSlice = append(tempSlice, cateId)
//通过上面的分类id,获取商品相关数据
goodsList := []models.Goods{}
where := "cate_id in ?"
models.DB.Where(where, tempSlice).Where("status = ?", 1).Offset((page - 1) * pageSize).Limit(pageSize).Find(&goodsList)
//获取总数量
var count int64
models.DB.Where(where, tempSlice).Table("goods").Count(&count)
//定义请求的模板
tpl := "frontend/product/list.html"
con.Render(c, tpl, gin.H{
"goodsList": goodsList, // 商品列表
"subCate": subCate, // 选择分类下面的子分类
"currentCate": curCate, // 当前分类
"page": page, //当前页码数
"totalPages": math.Ceil(float64(count) / float64(pageSize)), // 总页面数
})
}
[上一节][golang gin框架] 24.Gin 商城项目-redis讲解以及操作