电商项目商品详情页
对于商品详情页的视图大致思路
- 我们在点击商品进入详情页的过程中 , 浏览器会向服务端发送请求 , 我们可以是这个请求携带一个参数 , 也就是该商品的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 %}
在这整个过程中最大的问题就是 , 各种表关系之前的查询 , 以及规格的选择
如上图该商品对应的有规格和颜色 , 不同规格颜色应该是不同的商品才对 , 如黑色蓝色 , 每次在点击选择后就会更新到另一个商品 , 也就是说不仅仅需要从数据库中拿到数据 , 还需要设置更新 , 其中这部分的数据表结构也相当复杂 , 后面我会对表结构进行阐述
如上图该商品对应的有规格和颜色 , 不同规格颜色应该是不同的商品才对 , 如黑色蓝色 , 每次在点击选择后就会更新到另一个商品 , 也就是说不仅仅需要从数据库中拿到数据 , 还需要设置更新 , 其中这部分的数据表结构也相当复杂 , 后面我会对表结构进行阐述