美多商城之商品(商品详情页)

六、商品详情页

6.1 商品详情页分析和准备

美多商城之商品(商品详情页)

6.1.1. 商品详情页组成结构分析

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实现局部刷新效果。

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

1.请求方式

选项方案
请求方法

GET
请求地址

/detail/(?P

    #  商品详情
    url(r'^detail/(?P\d+)/$', views.DetailView.as_view(), name='detail'),

2.请求参数:路径参数

参数名类型是否必传说明
sku_id

string是商品SKU编号

3.响应结果:HTML

detail.html

4.接口定义

goods.views.py

class DetailView(View):
    """商品详情页"""

    def get(self, request, sku_id):
        """提供商品详情页"""
        return render(request, 'detail.html')

6.1.3. 商品详情页初步渲染

渲染商品频道分类、面包屑导航、商品热销排行

  • 将原先在商品列表页实现的代码拷贝到商品详情页即可。
  • 添加 detail.js
class DetailView(View):
    """商品详情页"""

    def get(self, request, sku_id):
        """提供商品详情页"""
        # 获取当前sku的信息
        try:
            sku = models.SKU.objects.get(id=sku_id)
        except models.SKU.DoesNotExist:
            return render(request, '404.html')

        # 查询商品频道分类
        categories = get_categories()
        # 查询面包屑导航
        breadcrumb = get_breadcrumb(sku.category)

        # 渲染页面
        context = {
            'categories':categories,
            'breadcrumb':breadcrumb,
            'sku':sku,
        }
        return render(request, 'detail.html', context)

提示:为了让前端在获取商品热销排行数据时,能够拿到商品分类ID,我们将商品分类ID从模板传入到Vue.js


    let category_id = "{{ sku.category.id }}";

data: {
    category_id: category_id,
},

6.2 展示详情页数据

6.2.1. 查询和渲染SKU详情信息

渲染页面
context = {
    'categories':categories,
    'breadcrumb':breadcrumb,
    'sku':sku,
}
return render(request, 'detail.html', context)

        {{ sku.name }}
        {{ sku.caption }}

            ¥{{ sku.price }}
            18人评价

            数 量:

                +
                -

        {#...商品规格...#}
        总价:[[ sku_amount ]]元

            加入购物车

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


    let sku_price = "{{ sku.price }}";

data: {
    sku_price: sku_price,
},

6.2.2. 查询和渲染SKU规格信息

1.查询SKU规格信息

class DetailView(View):
    """商品详情页"""

    def get(self, request, sku_id):
        """提供商品详情页"""
        # 获取当前sku的信息
        try:
            sku = models.SKU.objects.get(id=sku_id)
        except models.SKU.DoesNotExist:
            return render(request, '404.html')

        # 查询商品频道分类
        categories = get_categories()
        # 查询面包屑导航
        breadcrumb = get_breadcrumb(sku.category)

        # 构建当前商品的规格键
        sku_specs = sku.specs.order_by('spec_id')
        sku_key = []
        for spec in sku_specs:
            sku_key.append(spec.option.id)
        # 获取当前商品的所有SKU
        skus = sku.spu.sku_set.all()
        # 构建不同规格参数(选项)的sku字典
        spec_sku_map = {}
        for s in skus:
            # 获取sku的规格参数
            s_specs = s.specs.order_by('spec_id')
            # 用于形成规格参数-sku字典的键
            key = []
            for spec in s_specs:
                key.append(spec.option.id)
            # 向规格参数-sku字典添加记录
            spec_sku_map[tuple(key)] = s.id
        # 获取当前商品的规格信息
        goods_specs = sku.spu.specs.order_by('id')
        # 若当前sku的规格信息不完整,则不再继续
        if len(sku_key) < len(goods_specs):
            return
        for index, spec in enumerate(goods_specs):
            # 复制当前sku的规格键
            key = sku_key[:]
            # 该规格的选项
            spec_options = spec.options.all()
            for option in spec_options:
                # 在规格参数sku字典中查找符合当前规格的sku
                key[index] = option.id
                option.sku_id = spec_sku_map.get(tuple(key))
            spec.spec_options = spec_options

        # 渲染页面
        context = {
            'categories':categories,
            'breadcrumb':breadcrumb,
            'sku':sku,
            'specs': goods_specs,
        }
        return render(request, 'detail.html', context)

2.渲染SKU规格信息

{% for spec in specs %}

    {{ spec.name }}:
    {% for option in spec.spec_options %}
        {% if option.sku_id == sku.id %}
        {{ option.value }}
        {% elif option.sku_id %}
        {{ option.value }}
        {% else %}
        {{ option.value }}
        {% endif %}
    {% endfor %}

{% endfor %}

6.2.3. 查询和渲染详情、包装和售后信息

商品详情、包装和售后信息被归类到商品SPU中, sku.spu关联查询就可以找到该 SKUSPU信息。


        商品详情
        规格与包装
        售后服务
        商品评价(18)

            商品详情:
            {{ sku.spu.desc_detail|safe }}

            规格与包装:
            {{ sku.spu.desc_pack|safe }}

            售后服务:
            {{ sku.spu.desc_service|safe }}

            {#...商品评价...#}

美多商城之商品(商品详情页)

6.3 统计分类商品访问量

提示:

  • 统计分类商品访问量 是统计一天内该类别的商品被访问的次数。
  • 需要统计的数据,包括商品分类,访问次数,访问时间。
  • 一天内,一种类别,统计一条记录。

美多商城之商品(商品详情页)

6.3.1. 统计分类商品访问量模型类

模型类定义在 goods.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

美多商城之商品(商品详情页)

美多商城之商品(商品详情页)

【之前操作中修改了模型中的default_image_url的属性值,导致出现下面的错误】

美多商城之商品(商品详情页)

解决办法:【参考博文:https://www.cnblogs.com/erhangboke/p/11660133.html

美多商城之商品(商品详情页)

美多商城之商品(商品详情页)

6.3.2. 统计分类商品访问量后端逻辑

1.请求方式

选项方案
请求方法

POST
请求地址

/detail/visit/(?P

    #  统计商品的访问量
    url(r'^detail/visit/(?P\d+)/$', views.DetailVisitView.as_view()),

2.请求参数:路径参数

参数名类型是否必传说明
category_id

string是商品分类ID,第三级分类

3.响应结果:JSON

字段说明
code

状态码
errmsg

错误信息

4.后端接口定义和实现

  • 如果访问记录存在,说明今天不是第一次访问,不新建记录,访问量直接累加。
  • 如果访问记录不存在,说明今天是第一次访问,新建记录并保存访问量。
from django.utils import timezone
from datetime import datetime
import logging

 日志统计器
logger = logging.getLogger('django')

Create your views here.

class DetailVisitView(View):
    """详情页分类商品访问量"""

    def post(self, request, category_id):
        """记录分类商品访问量"""
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseForbidden('缺少必传参数')

        # 获取今天的日期
        t = timezone.localtime()
        today_str = '%d-%02d-%02d' % (t.year, t.month, t.day)
        today_date = datetime.strptime(today_str, '%Y-%m-%d')
        try:
            # 查询今天该类别的商品的访问量
            counts_data = category.goodsvisitcount_set.get(date=today_date)
        except GoodsVisitCount.DoesNotExist:
            # 如果该类别的商品在今天没有过访问记录,就新建一个访问记录
            counts_data = GoodsVisitCount()

        try:
            counts_data.category = category
            counts_data.count += 1
            counts_data.save()
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('服务器异常')

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})

美多商城之商品(商品详情页)

Original: https://blog.csdn.net/weixin_44799217/article/details/118642066
Author: IT之一小佬
Title: 美多商城之商品(商品详情页)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/736529/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Java简化代码推理,最终使用lamda表达式

    代码,自然写的越简洁越好啦,写的人舒服,看的人也舒服,一切为了高效。 要把有限的时间花到其它有意思的事情上去。 lamada表达式简化了匿名内部类。 函数接口 只有一个抽象方法的接…

    Python 2023年10月15日
    029
  • SKnet论文解读

    本文讲述sknet的核心部分:自适应性的注意力编码机制 SKNet 对不同输入使用的卷积核感受野不同,参数权重也不同,可以自适应的对输出进行处理 注:本人才疏学浅,文章难免有疏漏之…

    Python 2023年9月30日
    050
  • Web前端:Django和Angular——终极比较和差异

    世界各地的开发者都在采用AngularJS,因为它具有闪电般的开发速度以及开发具有改进 UI 的高度交互和用户友好的网站的能力。 Django是一个 Python 后端 Web 开…

    Python 2023年8月5日
    068
  • 【OpenCV 例程200篇】216. 绘制多段线和多边形

    专栏地址:『youcans 的 OpenCV 例程200篇』文章目录:『youcans 的 OpenCV 例程200篇-总目录』 【youcans 的 OpenCV 例程300篇】…

    Python 2023年8月28日
    049
  • Python数据处理numpy、pandas

    快速了解数据的行数和列数: df.shape() 快速了解数据的结构: df.info() 快速查看数据的描述性统计信息 df.decribe() #显示数值型数据的描述统计 简单…

    Python 2023年8月7日
    051
  • 关于linux的一点好奇心(五):进程线程的创建

    一直以来,进程和线程的区别,这种问题一般会被面试官拿来考考面试者,可见这事就不太简单。简单说一点差异是,进程拥有独立的内存资源信息,而线程则共享父进程的资源信息。也就是说线程不拥有…

    Python 2023年10月21日
    021
  • 故障诊断知识图谱

    该文档主要参考: 概述 该项目要求从网络上爬取相关设备故障和维修解决方式,并构建知识库,当设备出现故障时,用户通过输入数控机床相关参数(品牌、型号、故障代码、某个或多个超出阈值参数…

    Python 2023年9月30日
    049
  • matplotlib基础知识

    (一)基础知识 1.基础用法(figure,plot,show) plt.figure:定义一个figure图像窗口,可以有很多小图片 plt.plot:绘制曲线 plt.show…

    Python 2023年9月5日
    042
  • Web接收实时视频流并显示(flask创建路由接收)| 解决延时不同步问题

    在开发B/S架构的检测算法时,需要对摄像头实时视频流进行检测处理。下文代码能实现接收实时视频流到web端指定路由下进行播放。在后续开发中可继续将该路由视频流引入到相应的前端Html…

    Python 2023年8月11日
    068
  • [ Skill ] 文件读写 & IO 句柄

    在 Skill 中使用一种叫做 ioport 类型的变量来操作文件。不过我一般更习惯称为 IO 句柄 (IO/File Handle)。 常用下面两个函数来获得这些 IO 句柄: …

    Python 2023年6月16日
    078
  • Node.js基础入门第九天

    Express生成器 1. 什么是Express生成器 通过应用生成器工具 express-generator 可以快速创建一个基于Express的应用程序的骨架。 2. 安装Ex…

    Python 2023年6月10日
    071
  • Numpy基础练习100题[前50题]

    Numpy基础练习100题 项目来源:https://github.com/rougier/numpy-100 1.导入numpy库并取名字为np import numpy as …

    Python 2023年8月28日
    054
  • 组装三角形

    牛牛手里有N根木棒,分别编号为1~N,现在他从N根里想取出三根木棒,使得三根木棒构成一个三角形,你能计算出牛牛有多少种取法吗?(考虑两种取法中使用的木棒编号有一个不一样就认为是不同…

    Python 2023年5月24日
    0100
  • 基于Pycharm的Django学习 —— 项目实战(分页、cookie、session、中间件、Ajax)

    项目实战 * – 靓号管理 – + number_list + number_add + number_edit + number_delete + num…

    Python 2023年8月6日
    057
  • 我的 Kafka 旅程 – Consumer

    kafka采用Consumer消费者Pull主动拉取数据的方式,当Broker无数据时,消费者空转。Kafka并不删除已消费的消息,各自独立的消费者可消费同一个Broker分区数据…

    Python 2023年10月20日
    037
  • 改进YOLO:YOLOv5结合swin transformer

    文章参考于芒果大神 ,在自己的数据集上跑了一下,改了一些出现的错误。 一、配置yolov5_swin_transfomrer.yaml Parameters nc: 10 # nu…

    Python 2023年9月30日
    025
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球