商品详情页分析和准备
1.商品分类
2.面包屑
3.热销排行
4.商品名字、价格、数量、规格(颜色,内存,) 总价(和数量有关系)
5.商品详情 规格与包装 售后服务
6. 商品评价(完成下单后)

商品详情页组成结构分析
1.商品频道分类
• 已经提前封装在contents.utils.py文件中,直接调用方法即可。
2.面包屑导航
• 已经提前封装在goods.utils.py文件中,直接调用方法即可。
3.热销排行
• 该接口已经在商品列表页中实现完毕,前端直接调用接口即可。
4.商品SKU信息(详情信息)
• 通过sku_id可以找到SKU信息,然后渲染模板即可。
• 使用Ajax实现局部刷新效果。
5.SKU规格信息
• 通过SKU可以找到SPU规格和SKU规格信息。
6.商品详情介绍、规格与包装、售后服务
• 通过SKU可以找到SPU信息,SPU中可以查询出商品详情介绍、规格与包装、售后服务。
7.商品评价
• 商品评价需要在生成了订单,对订单商品进行评价后再实现,商品评价信息是动态数据。
• 使用Ajax实现局部刷新效果。

商品详情页接口设计和定义

1.请求方式
选项 方案
请求方法 GET
请求地址 /detail/(?P<sku_id>\d+)/

2.请求参数:路径参数
参数名 类型 是否必传 说明
sku_id string 是 商品SKU编号

3.响应结果:HTML
detail.html

4.接口定义

商品详情页
goods/views.py

class DetailDoodsView(View):"""商品详情页"""def get(self, request, sku_id):# 验证try:sku = SKU.objects.get(id=sku_id)except Exception as e:# return http.HttpResponseForbidden('参数sku_id不存在')return render(request, '404.html')# 查询商品分类categories = get_categories()# 查询面包屑breadcrumb = get_breadcrumb(sku.category)# 以下代码为整个项目最难理解的内容# 构建当前商品的规格键sku_specs = SKUSpecification.objects.filter(sku__id=sku_id).order_by('spec_id')sku_key = []for spec in sku_specs:sku_key.append(spec.option.id)# [1, 4, 7]   [8, 11]# print(sku_key)# 获取当前商品的所有SKUspu_id = sku.spu_idskus = SKU.objects.filter(spu_id=spu_id)# 构建不同规格参数(选项)的sku字典spec_sku_map = {}for s in skus:# 获取sku的规格参数s_specs = s.specs.order_by('spec_id')# print(s_specs.query)# 用于形成规格参数-sku字典的键key = []for spec in s_specs:key.append(spec.option.id)# 向规格参数-sku字典添加记录spec_sku_map[tuple(key)] = s.id# print(spec_sku_map)# 获取当前商品的规格信息goods_specs = SPUSpecification.objects.filter(spu_id=spu_id).order_by('id')# print(goods_specs)# 若当前sku的规格信息不完整,则不再继续# if len(sku_key) < len(goods_specs):#     returnfor index, spec in enumerate(goods_specs):# print(index, spec)# 复制当前sku的规格键key = sku_key[:]# 该规格的选项spec_options = spec.options.all()for option in spec_options:# 在规格参数sku字典中查找符合当前规格的skukey[index] = option.idoption.sku_id = spec_sku_map.get(tuple(key))spec.spec_options = spec_optionscontext = {"sku": sku,"categories": categories,"breadcrumb": breadcrumb,"specs": goods_specs}return render(request, 'detail.html', context=context)

detail.html
渲染SKU详情信息

<div class="goods_detail_con clearfix"><div class="goods_detail_pic fl"><img src="{{ sku.default_image.url }}"></div><div class="goods_detail_list fr"><h3>{{ sku.name }}</h3><p>{{ sku.caption }}</p><div class="price_bar"><span class="show_pirce">¥<em>{{ sku.price }}</em></span><a href="javascript:;" class="goods_judge">18人评价</a></div><div class="goods_num clearfix"><div class="num_name fl">数 量:</div><div class="num_add fl"><input v-model="sku_count" @blur="check_sku_count" type="text" class="num_show fl"><a @click="on_addition" class="add fr">+</a><a @click="on_minus" class="minus fr">-</a></div> </div>{#...商品规格...#}<div class="total" v-cloak>总价:<em>[[ sku_amount ]]元</em></div><div class="operate_btn"><a href="javascript:;" class="add_cart" id="add_cart">加入购物车</a>                </div></div>
</div>

为了实现用户选择商品数量的局部刷新效果,我们将商品单价从模板传入到Vue.js

<script type="text/javascript">let category_id = {{ sku.category.id }};let sku_price = {{ sku.price }};let sku_id = {{ sku.id }};</script>

统计分类商品的访问量
goodes/views.py

class DetailvisitView(View):"""统计分类商品的访问量"""def post(self, request, category_id):# 校验参数try:category = GoodsCategory.objects.get(id=category_id)except Exception as e:return http.HttpResponseForbidden('参数category_id不存在')t = timezone.localtime()# print(t)    # 2021-03-28 14:43:34.388257+08:00# 获取当前的时间字符串today_str = '%d-%02d-%02d' % (t.year, t.month, t.day)# print(today_str)# 保存# 需要在models.py中创建一张与访问量有关系的表# 分析字段应该包含:count(访问量)  category_id(商品) time (某一天)  user(可选)try:# 存在记录 修改记录 countcounts_data = GoodsVisitCount.objects.get(date=today_str, category=category.id)except GoodsVisitCount.DoesNotExist:# 不存在记录 新增counts_data = GoodsVisitCount()try:counts_data.category = categorycounts_data.count += 1counts_data.date = today_strcounts_data.save()except Exception as e:return http.HttpResponseServerError('统计失败')# 返回结果return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})

models.py

class GoodsVisitCount(BaseModel):"""统计分类商品访问量模型类"""category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name='商品分类')count = models.IntegerField(verbose_name='访问量', default=0)date = models.DateField(auto_now_add=True, verbose_name='统计日期')class Meta:db_table = 'tb_goods_visit'verbose_name = '统计分类商品访问量'verbose_name_plural = verbose_name

浏览记录 browse_histories/

当登录用户在浏览商品的详情页时,可以把详情页这件商品信息存储起来,作为该登录用户的浏览记录

存储数据说明:
浏览记录界面上要展示商品的一些SKU信息,但是在存储时没有必要存很多SKU信息。
选择存储SKU的唯一编号(sku_id)来表示该件商品浏览记录
存储数据:sku_id

存储位置说明
用户浏览记录时临时数据,且经常变化,数据量不大,所以选择内存型数据库进行存储
存储位置:Redis数据库 3号数据库

CACHES = {"history": { # 用户浏览记录"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379/3","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}},
}
选择数据类型分析:最新浏览的排在前面,如果保存浏览的个数是固定的,访问相同的商品前需删除先访问浏览过的商品,保留最近浏览品Redis数据类型有5种:String(字符串) Hash(哈希表)  List列表  Set集合  SortedSet(有序集合)要保留数据类型一定是key value(多个),排除用String(字符串),Hash(哈希表) 特点也是key value,只是value是一个字典,比如key是某一个用户,value如何设计?还要有序,添加,删除。List列表 :如同空心的竹子,从右边进是LPUSH,从左边进是RPUSH, 本项目存储可选择列表来处理:将sku_id往里面添加,遵守LPUSH和RPUSH就可以了,

存储类型说明
• 由于用户浏览记录跟用户浏览商品详情的顺序有关,所以我们选择使用Redis中的list类型存储 sku_id
• 每个用户维护一条浏览记录,且浏览记录都是独立存储的,不能共用。所以我们需要对用户的浏览记录进行唯一标识。
• 我们可以使用登录用户的ID来唯一标识该用户的浏览记录。
• 存储类型:‘history_user_id’ : [sku_id_1, sku_id_2, …]

Redis 命令参考
http://doc.redisfans.com/

LREM
LREM key count value
count 的值可以是以下几种:

count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。
count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。
count = 0 : 移除表中所有与 value 相等的值

根据参数 count 的值,移除列表中与参数 value 相等的元素
用第三种 count = 0 : 移除表中所有与 value 相等的值

LTRIM
LTRIM key start stop

对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。

举个例子,执行命令 LTRIM list 0 2 ,表示只保留列表 list 的前三个元素,其余元素全部删除。

下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。

你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

当 key 不是列表类型时,返回一个错误。

总结存储逻辑说明:
• SKU信息不能重复。
• 最近一次浏览的商品SKU信息排在最前面,以此类推。
• 每个用户的浏览记录最多存储五个商品SKU信息。
• 存储逻辑:先去重,再存储,最后截取。

保存和查询浏览记录

users/views.py

class UserBrowseHistory(LoginRequiredJSONMixin, View):"""用户浏览记录"""def post(self, request):"""保存用户的商品浏览记录"""json_str = request.body.decode()json_dict = json.loads(json_str)sku_id = json_dict.get('sku_id')# 校验参数try:SKU.objects.get(id=sku_id)except SKU.DoesNotExist:return http.HttpResponseForbidden('sku_id不存在')redis_conn = get_redis_connection('history')user = request.userpl = redis_conn.pipeline()# 去重复pl.lrem('history_%s' % user.id, 0, sku_id)# 保存pl.lpush('history_%s' % user.id, sku_id)# 截取 需求是保存5个商品 0, 4pl.ltrim('history_%s' % user.id, 0, 4)# 执行pl.execute()# 响应结果return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})def get(self, request):"""查询用户商品浏览记录"""redis_conn = get_redis_connection('history')user = request.usersku_ids = redis_conn.lrange('history_%s' % user.id, 0, -1)# print(sku_ids)skus = []for sku_id in sku_ids:sku = SKU.objects.get(id=sku_id)skus.append({"id": sku.id,"name": sku.name,"price": sku.price,"default_image_url": sku.default_image.url})return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'skus': skus})

user_conter_info.html

<h3 class="common_title2">最近浏览</h3><div class="has_view_list" v-cloak><ul class="goods_type_list clearfix"><li v-for="sku in histories"><a :href="sku.url"><img :src="sku.default_image_url"></a><h4><a :href="sku.url">[[ sku.name ]]</a></h4><div class="operate"><span class="price">¥[[ sku.price ]]</span><span class="unit">台</span><a href="javascript:;" class="add_goods" title="加入购物车"></a></div>

user_conter_info.js

      // 请求浏览历史记录browse_histories(){let url = '/users/browse_histories/';axios.get(url, {responseType: 'json'}).then(response => {this.histories = response.data.skus;for(let i=0; i<this.histories.length; i++){this.histories[i].url = '/detail/' + this.histories[i].id + '/';}}).catch(error => {console.log(error.response);})},


Django项目-商品详情页相关推荐

  1. 微信小程序电商项目商品详情页开发实战之数据绑定与事件应用

    各位CSDN的朋友,我们都知道,现在微信小程序电商平台特别火爆,所以我将以一个生鲜电商项目为例,为大家讲述微信小程序的实战化开发,价值几万元的成熟项目,你可千万不要错过哦. 大家直接通过视频链接直接看 ...

  2. 电商项目商品详情页架构设计

    当用户进入京东首页,点击搜索手机进入搜索页面,点击一款手机进入商品详情页面,主要展示商品的信息,主要分为三块信息: 1:基本信息:展示商品的基本信息,包括sku价格等基本信息. 2:商品描述(商品详情 ...

  3. 61分布式电商项目 - 商品详情页

    需求分析 运用 Freemarker 技术来实现商品详细页的静态化.通过地址栏输入某地址,如下形式 http://localhost:9101/gen_item.do?goodsId=14918784 ...

  4. 电商项目-商品详情页的实现

    1. 需要做的事情 l 商品详情页实现 1.商品查询服务事项 2.商品详情展示 3.添加缓存 2. 实现商品详情页功能 2.1. 功能分析 1.Taotao-portal接收页面请求,接收到商品id. ...

  5. Django电商项目(六)商品详情页、列表页分页、商品搜索

    Django电商项目 商品详情页 商品列表页 商品搜索 全文检索 安装和配置 索引文件生成 全文检索的使用 改变分词方式 商品详情页 新建detail.html {% extends 'base_de ...

  6. 高并发处理之商品详情页

    首页 博客 专栏·视频 下载 论坛 问答 代码 直播 能力认证 高校 会员中心 收藏 动态 消息 创作中心 高并发处理之商品详情页 卜大伟 2019-01-18 11:13:47  2488  收藏  ...

  7. Django项目实战——14—(列表页热销排行、商品搜索、Haystack建立数据索引、渲染商品搜索结果、商品详情页)

    1.列表页热销排行 根据路径参数category_id查询出该类型商品销量前二的商品. 使用Ajax实现局部刷新的效果. 查询列表页热销排行数据 请求方式 请求参数:路径参数 响应结果:JSON {& ...

  8. Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)十六(商品排序,Thymeleaf快速入门,商品详情页的展示)

    Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)十六(商品详情页的展示) 一.商品排序 1.完善页面信息 这是用来做排序的,默认按照综合排序 ...

  9. SpringBoot--网上商城项目(自定义的参数解析器、购物车后台前台功能、商品详情页)

    目录 一.自定义的参数解析器 关于Mybatis-plus时间字段代码生成问题 报错信息:Caused by: java.lang.IllegalStateException: No typehand ...

最新文章

  1. 有关增强现实技术的过去、现在和未来的发展
  2. ubuntu mysql5.6 编译安装_Ubuntu14.04编译安装mysql5.6.26
  3. sql server image字段的转换
  4. SimpleAdapter理解
  5. 【Linux】一步一步学Linux——dpkg-divert命令(273)
  6. Nacos源码发送心跳
  7. hive简介以及安装配置
  8. latex学习篇【一】论文中的图片技巧QA
  9. java 调用groovy_Java调用Groovy脚本
  10. Win11连接WiFi后显示无Internet访问权限怎么办?
  11. Android 与 unity3d 基于微信授权、支付、分享,QQ分享,支付宝支付的交互
  12. 1. Browser 对象 - Window 对象
  13. 7-汇编大小写字符互相转化+[bx+idata]+SI/DI
  14. SNMP:简单网络管理协议(一)
  15. linux centos dhcpd进程,centos7 – 如何在Centos 7上忽略dhcpd中未使用的网络接口
  16. (转)wuauclt.exe病毒解决方案
  17. 视频播放可弹出弹幕,关闭弹幕
  18. vue 分割面板组件
  19. 朝雨的方向,梦回故里
  20. 可行解、最优解、基解、基可行解、基最优解

热门文章

  1. ssh 链接不上虚拟机 ping不通虚拟机 而且防火墙已经关闭的状态下
  2. 荣耀X30卸载软件补充
  3. qtractor教程_用Qtractor放一些音轨
  4. 四川小学计算机的组成是几年级学,浅谈小学计算机教学_小学四年级计算机
  5. 硬盘使用时间可以改吗? 如何修改呢
  6. Java去掉html标签的各种姿势
  7. 【英语六级作文】必背万能模板句型
  8. 智慧长沙发展规划印发:2020年市民可享多项便利
  9. Can't connect to any repository
  10. mysql查询前五行_性能监控实战