电商项目商品详情页
对于商品详情页的视图大致思路
- 我们在点击商品进入详情页的过程中 , 浏览器会向服务端发送请求 , 我们可以是这个请求携带一个参数 , 也就是该商品的ID
- 在获取到商品的ID后 , 我们就可以在后端编写 , 通过这个ID 从数据库中拿到相应的数据 , 返回在前端页面中
设置路由
re_path('^detail/(?P<sku_id>\d+)/$' , views.DetailView.as_view() , name='detail'),
视图
# 详情页数据 class DetailView(View): ''' 商品详情页 ''' def get(self , request , sku_id): categories = get_category() sku = SKU.objects.get(id=sku_id) breadcrumb = get_breadcrumb(sku.category) # 通过 sku.id 获取商品对象的对应规格信息的选项 sku_specs = SKUSpecification.objects.filter(sku_id=sku_id).order_by('spec_id') # 创建一个空的列表 用来存储当前 sku 对应的规格选项数据 sku_key = [] # 遍历当前 sku 的规格选项 for spec in sku_specs: # 将每个规格选项的 ID 添加到 sku_key 列表中 sku_key.append(spec.option.id) # [8, 11] 颜色:金色 ,内存:64GB # [1, 4, 7] 屏幕尺寸:13.3英寸 颜色:银色 ,内存:core i5/8G内存/512G存储 # 获取当前商品的所有 sku # 保证选择不同的规格的情况下 , 商品不变 spu_id = sku.spu_id spu = SPU.objects.get(id=spu_id) skus = SKU.objects.filter(spu_id=spu_id) # 构建商品的不同规格参数,sku的选项字段 spec_sku_map = {} for i in skus: # 获取sku规格的参数 s_pecs = i.specs.order_by('spec_id') # 创建一个空列表 , 用于存储 sku 规格参数 key = [] # 遍历当前 sku 规格参数列表 for spec in s_pecs: key.append(spec.option.id) spec_sku_map[tuple(key)] = i.id # 获取当前商品的规格名称 # 根据商品的 ID 获取当前商品的所有规格名称 goods_specs = SPUSpecification.objects.filter(spu_id=spu_id).order_by('id') # 前端渲染 # 实现根据规格选项生成对应 sku.id, 更新规格对象个规格选项信息。 # 为了给用户展示所有的规格参数 for index , spec in enumerate(goods_specs): # 复制 sku_key 列表中的数据,避免直接 sku_key 列表中的内容 key = sku_key[:] # 获取当前 specs 对象的规格名称 spec_options = spec.options.all() # 遍历当前商品的规格名称 for spec_option in spec_options: # 将当前规格选项对象 spec_option 的 id 赋值给 key列表中 index 的位置,用于查询对应 sku 参数内容 key[index] = spec_option.id # 根据列表中的值, 在 spec_sku_map 字典中查询对应的 sku 数据 spec_option.sku_id = spec_sku_map.get(tuple(key)) # 更新每个规格对象的选项内容 spec.spec_options = spec_options context = { 'categories' : categories, 'breadcrumb' : breadcrumb, 'sku':sku, 'specs' : goods_specs, 'spu' : spu } return render(request , 'detail.html' , context=context)
修改前段
{% for group in categories.values %} <li> <div class="level1"> {% for channel in group.channels %} <a href="{{ channel.url }}">{{ channel.name }}</a> {% endfor %} </div> <div class="level2"> {% for cat2 in group.sub_cats %} <div class="list_group"> <div class="group_name fl">{{ cat2.name }} ></div> <div class="group_detail fl"> {% for cat3 in cat2.sub_cat %} <a href="/list/{{ cat3.id }}/1/">{{ cat3.name }}</a> {% endfor %} </div> </div> {% endfor %} </div> </li> {% endfor %}
{% for spec in specs %} <div class="type_select"> <label>{{ spec.name }}:</label> {% for option in spec.spec_options %} {% if option.sku_id == sku.id %} <a href="javascript:;" class="select">{{ option.value }}</a> {% elif option.sku_id %} <a href="{% url 'detail' option.sku_id %}">{{ option.value }}</a> {% else %} <a href="javascript:;">{{ option.value }}</a> {% endif %} {% endfor %} </div> {% endfor %}
在这整个过程中最大的问题就是 , 各种表关系之前的查询 , 以及规格的选择
电商项目商品详情页
对于商品详情页的视图大致思路
- 我们在点击商品进入详情页的过程中 , 浏览器会向服务端发送请求 , 我们可以是这个请求携带一个参数 , 也就是该商品的ID
- 在获取到商品的ID后 , 我们就可以在后端编写 , 通过这个ID 从数据库中拿到相应的数据 , 返回在前端页面中
设置路由
re_path('^detail/(?P<sku_id>\d+)/$' , views.DetailView.as_view() , name='detail'),
视图
# 详情页数据 class DetailView(View): ''' 商品详情页 ''' def get(self , request , sku_id): categories = get_category() sku = SKU.objects.get(id=sku_id) breadcrumb = get_breadcrumb(sku.category) # 通过 sku.id 获取商品对象的对应规格信息的选项 sku_specs = SKUSpecification.objects.filter(sku_id=sku_id).order_by('spec_id') # 创建一个空的列表 用来存储当前 sku 对应的规格选项数据 sku_key = [] # 遍历当前 sku 的规格选项 for spec in sku_specs: # 将每个规格选项的 ID 添加到 sku_key 列表中 sku_key.append(spec.option.id) # [8, 11] 颜色:金色 ,内存:64GB # [1, 4, 7] 屏幕尺寸:13.3英寸 颜色:银色 ,内存:core i5/8G内存/512G存储 # 获取当前商品的所有 sku # 保证选择不同的规格的情况下 , 商品不变 spu_id = sku.spu_id spu = SPU.objects.get(id=spu_id) skus = SKU.objects.filter(spu_id=spu_id) # 构建商品的不同规格参数,sku的选项字段 spec_sku_map = {} for i in skus: # 获取sku规格的参数 s_pecs = i.specs.order_by('spec_id') # 创建一个空列表 , 用于存储 sku 规格参数 key = [] # 遍历当前 sku 规格参数列表 for spec in s_pecs: key.append(spec.option.id) spec_sku_map[tuple(key)] = i.id # 获取当前商品的规格名称 # 根据商品的 ID 获取当前商品的所有规格名称 goods_specs = SPUSpecification.objects.filter(spu_id=spu_id).order_by('id') # 前端渲染 # 实现根据规格选项生成对应 sku.id, 更新规格对象个规格选项信息。 # 为了给用户展示所有的规格参数 for index , spec in enumerate(goods_specs): # 复制 sku_key 列表中的数据,避免直接 sku_key 列表中的内容 key = sku_key[:] # 获取当前 specs 对象的规格名称 spec_options = spec.options.all() # 遍历当前商品的规格名称 for spec_option in spec_options: # 将当前规格选项对象 spec_option 的 id 赋值给 key列表中 index 的位置,用于查询对应 sku 参数内容 key[index] = spec_option.id # 根据列表中的值, 在 spec_sku_map 字典中查询对应的 sku 数据 spec_option.sku_id = spec_sku_map.get(tuple(key)) # 更新每个规格对象的选项内容 spec.spec_options = spec_options context = { 'categories' : categories, 'breadcrumb' : breadcrumb, 'sku':sku, 'specs' : goods_specs, 'spu' : spu } return render(request , 'detail.html' , context=context)
修改前段
{% for group in categories.values %} <li> <div class="level1"> {% for channel in group.channels %} <a href="{{ channel.url }}">{{ channel.name }}</a> {% endfor %} </div> <div class="level2"> {% for cat2 in group.sub_cats %} <div class="list_group"> <div class="group_name fl">{{ cat2.name }} ></div> <div class="group_detail fl"> {% for cat3 in cat2.sub_cat %} <a href="/list/{{ cat3.id }}/1/">{{ cat3.name }}</a> {% endfor %} </div> </div> {% endfor %} </div> </li> {% endfor %}
{% for spec in specs %} <div class="type_select"> <label>{{ spec.name }}:</label> {% for option in spec.spec_options %} {% if option.sku_id == sku.id %} <a href="javascript:;" class="select">{{ option.value }}</a> {% elif option.sku_id %} <a href="{% url 'detail' option.sku_id %}">{{ option.value }}</a> {% else %} <a href="javascript:;">{{ option.value }}</a> {% endif %} {% endfor %} </div> {% endfor %}
在这整个过程中最大的问题就是 , 各种表关系之前的查询 , 以及规格的选择
如上图该商品对应的有规格和颜色 , 不同规格颜色应该是不同的商品才对 , 如黑色蓝色 , 每次在点击选择后就会更新到另一个商品 , 也就是说不仅仅需要从数据库中拿到数据 , 还需要设置更新 , 其中这部分的数据表结构也相当复杂 , 后面我会对表结构进行阐述
如上图该商品对应的有规格和颜色 , 不同规格颜色应该是不同的商品才对 , 如黑色蓝色 , 每次在点击选择后就会更新到另一个商品 , 也就是说不仅仅需要从数据库中拿到数据 , 还需要设置更新 , 其中这部分的数据表结构也相当复杂 , 后面我会对表结构进行阐述