def generate_static_sku_detail_html(sku_id): """ 生成静态商品详情页面 :param sku_id: 商品sku id :return: """ # 查询sku信息 sku = SKU.objects.get(id=sku_id) # 查询商品频道分类 categories = get_categories() # 查询面包屑导航 bread_crumb = get_breadcrumb(sku.category) # 构建当前商品的规格 goods_specs = get_goods_specs(sku) # 构建上下文 context = { 'categories': categories, 'bread_crumb': bread_crumb, 'sku': sku, 'specs': goods_specs } # 获取详情页模板文件 template = loader.get_template('detail.html') # 渲染详情页html字符串 detail_html_text = template.render(context) # 将详情页html字符串写入到指定目录,命名'index.html' file_path = os.path.join(settings.STATICFILES_DIRS[0], 'detail/' + str(sku_id) + '.html') with open(file_path, 'w', encoding='utf-8') as f: f.write(detail_html_text)
def get(self, request, sku_id): ''' 根据sku_id 获取对应的商品, 整理格式, 返回 :param request: :param sku_id: :return: ''' # 1.根据sku_id 获取对应的商品 data = get_goods_and_spec(sku_id, request) # 3.获取商品分类 categories = get_categories() breadcrumb = get_breadcrumb(data.get('goods').category3) # 4.整理格式 context = { 'categories': categories, 'sku': data.get('sku'), 'goods': data.get('goods'), 'specs': data.get('goods_specs'), 'breadcrumb': breadcrumb } # 5.返回 return render(request, 'detail.html', context)
def generate_static_sku_detail_html(sku_id): """ 生成静态商品详情页面 :param sku_id: 商品sku id """ sku = SKU.objects.get(id=sku_id) category = sku.category spu = sku.spu """1.准备当前商品的规格选项列表 [8, 11]""" # 获取出当前正显示的sku商品的规格选项id列表 current_sku_spec_qs = sku.specs.order_by('spec_id') current_sku_option_ids = [] # [8, 11] for current_sku_spec in current_sku_spec_qs: current_sku_option_ids.append(current_sku_spec.option_id) """2.构造规格选择仓库 {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8} """ # 构造规格选择仓库 temp_sku_qs = spu.sku_set.all() # 获取当前spu下的所有sku # 选项仓库大字典 spec_sku_map = { } # {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8} for temp_sku in temp_sku_qs: # 查询每一个sku的规格数据 temp_spec_qs = temp_sku.specs.order_by('spec_id') temp_sku_option_ids = [] # 用来包装每个sku的选项值 for temp_spec in temp_spec_qs: temp_sku_option_ids.append(temp_spec.option_id) spec_sku_map[tuple(temp_sku_option_ids)] = temp_sku.id """3.组合 并找到sku_id 绑定""" spu_spec_qs = spu.specs.order_by('id') # 获取当前spu中的所有规格 for index, spec in enumerate(spu_spec_qs): # 遍历当前所有的规格 spec_option_qs = spec.options.all() # 获取当前规格中的所有选项 temp_option_ids = current_sku_option_ids[:] # 复制一个新的当前显示商品的规格选项列表 for option in spec_option_qs: # 遍历当前规格下的所有选项 temp_option_ids[index] = option.id # [8, 12] option.sku_id = spec_sku_map.get( tuple(temp_option_ids)) # 给每个选项对象绑定下他sku_id属性 spec.spec_options = spec_option_qs # 把规格下的所有选项绑定到规格对象的spec_options属性上 context = { 'categories': get_categories(), # 商品分类 'breadcrumb': get_breadcrumb(category), # 面包屑导航 'sku': sku, # 当前要显示的sku模型对象 'category': category, # 当前的显示sku所属的三级类别 'spu': spu, # sku所属的spu 'spec_qs': spu_spec_qs, # 当前商品的所有规格数据 } response = render(None, 'detail.html', context) html_text = response.content.decode() # 将首页html字符串写入到指定目录,命名'index.html' file_path = os.path.join(settings.STATICFILES_DIRS[0], "detail/" + str(sku_id) + ".html") with open(file_path, "w", encoding="utf-8") as f: f.write(html_text)
def get(self, request, sku_id): """ 获取商品详情页 :param request: :param sku_id: :return: """ # 获取商品频道分类 categories = get_categories() sku = SKU.objects.get(id=sku_id) category = sku.category # 获取商品sku规格 data = get_goods_and_spec(sku_id, request) # 根据商品类别id获取商品导航页 breadcrumb = get_breadcrumb(category) # 组合参数 context = { 'categories': categories, 'goods': data.get('goods'), 'sku': data.get('sku'), 'specs': data.get('goods_specs'), 'breadcrumb': breadcrumb, } # 进行返回 return render(request, 'detail.html', context=context)
def get(self, request, sku_id): """提供商品详情页""" # 商品分类菜单 categories = get_categories() try: sku = SKU.objects.get(id=sku_id) sku.images = sku.skuimage_set.all() except SKU.DoesNotExist: return render(request, '404.html') # 面包屑导航 category = sku.category breadcrumb = get_breadcrumb(category) # 调用封装的函数, 根据 sku_id 获取对应的 # 1. 类别( sku ) # 2. 商品( goods ) # 3. 商品规格( spec ) data = get_goods_and_spec(sku_id, request) # 拼接参数,生成静态 html 文件 context = { 'categories': categories, 'goods': data.get('goods'), 'specs': data.get('goods_specs'), 'sku': data.get('sku'), 'breadcrumb': breadcrumb, } return render(request, 'detail.html', context)
def generate_static_sku_detail_html(sku): categories = get_categories() breadcrumb = get_breadcrumb(sku.category.id) goods, sku, specs = get_goods_and_spec(sku.id) # 1、构建模版参数 context = { 'categories': categories, # 渲染分类 'breadcrumb': breadcrumb, # 渲染导航 'goods': goods, # 商品价格等信息 'sku': sku, # 商品价格等信息 'specs': specs, # 商品规格信息 } # 2、获取模版对象 template = loader.get_template('detail.html') # 3、渲染页面 html = template.render(context=context) detail_html_dir = os.path.join( os.path.dirname(os.path.dirname(settings.BASE_DIR)), 'front_end_pc/goods' ) # 4、保存静态文件 —— front_end_pc/goods文件夹中保存,并且以sku的id作为文件名 with open(os.path.join(detail_html_dir, '%d.html'%sku.id), 'w') as f: f.write(html)
def generate_static_sku_detail_html(sku_id): """ 生成静态商品详情页面 :param sku_id: 商品sku id """ # 获取当前sku的信息 sku = models.SKU.objects.get(id=sku_id) # 查询商品频道分类 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, } template = loader.get_template('detail.html') html_text = template.render(context) file_path = os.path.join(settings.STATICFILES_DIRS[0], 'detail/' + str(sku_id) + '.html') with open(file_path, 'w') as f: f.write(html_text)
def generate_detail_html(sku_id): sku = SKU.objects.get(id=sku_id) # 通过sku获取三级目录商品 category = sku.category # categories = get_categories() # breadcrumb = get_breadcrumb(category) spu = sku.spu # 1, 获得当前sku的规格 current_sku_spec_qs = sku.specs.order_by('spec_id') current_sku_option_ids = [] for current_sku_spec in current_sku_spec_qs: current_sku_option_ids.append(current_sku_spec.option_id) # 2, 获得spu的所有规格包装 # 获得所有spu下的sku sku_qs = spu.sku_set.all() # {(8,11): 3, (8,12): 4....} all_spec_dict = {} for every_sku in sku_qs: # 查每个sku对应的规格 every_sku_spec_qs = every_sku.specs.order_by('spec_id') every_sku_option_ids = [] for every_sku_spec in every_sku_spec_qs: every_sku_option_ids.append(every_sku_spec.option_id) all_spec_dict[tuple(every_sku_option_ids)] = every_sku.id # 3, 与 sku_id进行绑定 # 获取此商品对应spu的所有规格名称 spu_spec_qs = spu.specs.order_by('id') # 遍历spu的所有规格得到每一个规格, 其属性就是每个规格对应的所有规格值, for index, spu_spec in enumerate(spu_spec_qs): spu_option_qs = spu_spec.options.all() temp_option_ids = current_sku_option_ids[:] for option in spu_option_qs: temp_option_ids[index] = option.id option.sku_id = all_spec_dict.get(tuple(temp_option_ids)) spu_spec.spu_option = spu_option_qs context = { 'categories': get_categories(), 'breadcrumb': get_breadcrumb(category), 'sku': sku, 'spu_spec_qs': spu_spec_qs, 'spu': spu, 'category': category } template = loader.get_template('detail.html') html_text = template.render(context) file_path = os.path.join(settings.STATICFILES_DIRS[0], 'detail/' + str(sku_id) + '.html') with open(file_path, 'w') as f: f.write(html_text)
def get(self, request, category_id, page_num): """提供商品列表页""" # 判断category_id是否正确 try: # 获取三级菜单分类信息 category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return HttpResponseNotFound('GoodsCategory 不存在') # 查询商品频道分类 categories = get_categories() # 查询面包屑导航 breadcrumb = get_breadcrumb(category) # 接收sort参数:如果用户不传,就是默认的排序规则 sort = request.GET.get('sort','defayle') # 按照排序规则查询该分类商品SKU信息 if sort == 'price': sortkind = 'price' elif sort == 'hot': sortkind = '-sales' else: # 'price'和'sales'以外的所有排序方式都归为'default' sortkind = 'create_time' # 获取当前分类并且上架的商品(并且对商品按照排序字段进行排序) skus = SKU.objects.filter(category=category,is_launched=True).order_by(sortkind) # 创建分页器:每页N条记录 # 列表页每页商品数据量 # GOODS_LIST_LIMIT = 5 paginator = Paginator(skus,5) try: # 分页后数据 page_skus = paginator.page(page_num) except EmptyPage: # 如果page_num不正确,默认给用户404 return HttpResponseNotFound('empty page') # 获取列表页总页数 total_page = paginator.num_pages # 渲染页面 context = { 'categories':categories, # 频道分类 'breadcrumb':breadcrumb, # 面包屑导航 'sort': sort, # 排序字段 'category': category, # 第三级分类 'page_skus': page_skus, # 分页后数据 'total_page': total_page, # 总页数 'page_num': page_num, # 当前页码 } return render(request, 'list.html',context)
def get(self, request, sku_id): """提供商品详情页""" # 接收和校验参数 try: # 查询sku sku = SKU.objects.get(id=sku_id) except SKU.DoesNotExist: # return http.HttpResponseNotFound('sku_id 不存在') 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)
def get(self, request, category_id, page_num): """查询并渲染商品列表页""" # 接收参数 sort = request.GET.get('sort', 'default') # 校验参数 try: category3 = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return http.HttpResponseForbidden('参数category_id有误') # 先排序查询:排序字段必须是模型类某个属性 if sort == 'price': # 按照价格由低到高排序 sort_field = 'price' elif sort == 'hot': # 按照销量有高到底排序 sort_field = '-sales' else: # 按照创建时间排序,新品在前 sort = 'default' # 无论用户传的是什么,这里都重置为default sort_field = '-create_time' skus = SKU.objects.filter(category_id=category_id, is_launched=True).order_by(sort_field) # 再分页查询 Paginator 分页器 # 创建分页器:对skus进行分页,每页5条记录 paginator = Paginator(skus, 5) # 查询指定页对应的数据 try: page_skus = paginator.page(page_num) except EmptyPage: return render(request, '404.html') # 总共分了多少页 total_count = paginator.num_pages # 查询商品分类 categories = get_categories() # 查询面包屑导航 # cat2 = category3.parent # cat1 = cat2.parent # bread_crumb = { # 'cat1': cat1, # 'cat2': cat2, # 'cat3': category3 # } bread_crumb = get_breadcrumb(category3) # 查询热销排行 context = { 'category_id': category_id, 'sort': sort, 'page_skus': page_skus, 'page_num': page_num, 'total_count': total_count, 'categories': categories, 'bread_crumb': bread_crumb } return render(request, 'list.html', context)
def get(self, request, sku_id): """提供商品詳情頁""" # 接收參數和校驗參數 try: sku = SKU.objects.get(id=sku_id) except SKU.DoesNotExist: return render(request, '404.html') # 查詢商品分類 categories = get_categories() # 查詢麵包屑導航 breadcrump = 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': breadcrump, 'sku': sku, 'specs': goods_specs, } return render(request, 'detail.html', context)
def get(self, request, sku_id): # 接收sku_id 并且校验参数是否存在 try: sku = SKU.objects.get(id=sku_id) except 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_spacs = sku.spu.specs.order_by('id') # 若当前sku信息不完整,则不再继续 if len(sku_key) < len(goods_spacs): return render(request, '404.html') for index, spec in enumerate(goods_spacs): key = sku_key[:] spec_options = spec.options.all() for option in spec_options: 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_spacs, } return render(request, 'detail.html', context)
def get(self, request, category_id): '''接收商品的三级分类id,获取对应的商品,排序后分页返回''' # 1.接收参数(查询字符串) page = request.GET.get('page') page_size = request.GET.get('page_size') ordering = request.GET.get('ordering') # 2.根据三级类别id, 获取对应的类别 try: category = GoodsCategory.objects.get(id=category_id) except Exception as e: return JsonResponse({'code': 400, 'errmsg': '根据id获取类别出错'}) # 根据category获取对应的面包屑效果数据: dict = get_breadcrumb(category) try: # 3.根据该类别,去商品表查询商品(该类别, 上架的), 安装前端传入的参数排序 skus = SKU.objects.filter(category=category, is_launched=True).order_by(ordering) except Exception as e: return JsonResponse({'code': 400, 'errmsg': '获取对应的商品出错'}) # 4.根据分页类, 创建分页对象 paginator = Paginator(skus, page_size) # 5.调用分页对象的page(页码),获取对应该页码的商品 try: page_skus = paginator.page(page) except EmptyPage: return JsonResponse({'code': 400, 'errmsg': 'page页码出错'}) # 6.调用分页对象的num_pages: 获取总页码 totoal_pages = paginator.num_pages list = [] # 7.遍历获取对应该页码的商品, 拿取每一个, 拼接参数 for sku in page_skus: list.append({ 'id': sku.id, 'name': sku.name, 'default_image_url': sku.default_image_url, 'price': sku.price }) # 8.整理格式, 返回 return JsonResponse({'code': 0, 'errmsg': 'ok', 'breadcrumb': dict, 'list': list, 'count': totoal_pages})
def get(self, request, category_id, page_num): """查询并渲染商品列表页""" # 校验参数category_id的范围 : 1111111111111111111111111111111 try: # 三级类别 category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return http.HttpResponseForbidden('参数category_id不存在') # 获取sort(排序规则): 如果sort没有值,取'default' sort = request.GET.get('sort', 'default') # 根据sort选择排序字段,排序字段必须是模型类的属性 if sort == 'price': sort_field = 'price' # 按照价格由低到高排序 elif sort == 'hot': sort_field = '-sales' # 按照销量由高到低排序 else: # 只要不是'price'和'-sales'其他的所有情况都归为'default' sort = 'default' # 当出现?sort=itcast 也把sort设置我'default' sort_field = 'create_time' # 查询商品分类 categories = get_categories() # 查询面包屑导航:一级 -> 二级 -> 三级 breadcrumb = get_breadcrumb(category) # 分页和排序查询:category查询sku,一查多,一方的模型对象.多方关联字段.all/filter # skus = SKU.objects.filter(category=category, is_launched=True) # 无经验查询 # skus = SKU.objects.filter(category_id=category_id, is_launched=True) # 无经验查询 # skus = category.sku_set.filter(is_launched=True).order_by('排序字段:create_time,price,-sales') # 有经验查询 skus = category.sku_set.filter(is_launched=True).order_by(sort_field) # 有经验查询 # 创建分页器 # Paginator('要分页的记录', '每页记录的条数') paginator = Paginator(skus, 5) # 把skus进行分页,每页5条记录 # 获取到用户当前要看的那一页(核心数据) try: page_skus = paginator.page(page_num) # 获取到page_num页中的五条记录 except EmptyPage: return http.HttpResponseNotFound('Empty Page') # 获取总页数:前端的分页插件需要使用 total_page = paginator.num_pages # 构造上下文 context = { 'categories': categories, 'breadcrumb': breadcrumb, 'page_skus': page_skus, 'total_page': total_page, 'page_num': page_num, 'sort': sort, 'category_id': category_id } return render(request, 'list.html', context)
def get(self, request, category_id): '''返回列表页中的排过序并且分页的数据''' # 1.接收参数 page = request.GET.get('page') page_size = request.GET.get('page_size') ordering = request.GET.get('ordering') # 2.根据category_id获取对应的三级类别 try: category = GoodsCategory.objects.get(id=category_id) except Exception as e: return JsonResponse({'code':400, 'errmsg':'获取三级类别出错'}) # 3.TODO:根据三级类别获取面包屑数据(待做) breadcrumb = get_breadcrumb(category) # 4.获取该三级类别下的所有商品, 根据前端传的数据排序 try: skus = SKU.objects.filter(category=category, is_launched=True).order_by(ordering) except Exception as e: return JsonResponse({'code': 400, 'errmsg': '获取商品出错'}) # 5.把所有数据进行分页 paginator = Paginator(skus, page_size) # 6.获取 当前页码 的所有商品 try: per_pages_skus = paginator.page(page) except EmptyPage as e: return JsonResponse({'code': 400, 'errmsg': '获取对应页吗数据出错'}) # 7.获取所有的总页码 total_pages = paginator.num_pages list = [] # 8.把当前页码的所有商品遍历, 获取每一个 for sku in per_pages_skus: # 9.把每一个商品的数据(图片&标题&加个&id) ---> {} ===> [] list.append({ 'id':sku.id, 'name':sku.name, 'price':sku.price, 'default_image_url':sku.default_image.url }) # 10.返回json数据 return JsonResponse({'code':0, 'errmsg':'ok', 'breadcrumb':breadcrumb, 'list':list, 'count':total_pages})
def get(self, request, category_id, page_num): """查詢並渲染商品表""" try: category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: http.HttpResponseForbidden('參數category_id不存在') # 獲取sort排序, 如果sort沒有值, 默認取default sort = request.GET.get('sort', 'default') # 根據sort選擇排序欄位,欄位必須是模型類的屬性 if sort == 'price': sort_field = 'price' # 價格低到高 elif sort == 'hot': sort_field = '-sales' # 銷量高到低 else: sort = 'default' sort_field = 'create_time' # 查詢商品分類 categories = get_categories() # 麵包屑導航 breadcrumb = get_breadcrumb(category) # 分頁和排序查詢 category查詢sku 一對多 #skus = SKU.objects.filter(category=category, is_launched=True).order_by(sort_field) skus = category.sku_set.filter(is_launched=True).order_by(sort_field) # 創建分頁器 paginator = Paginator(skus, 5) try: # 獲取用戶當前要看的那頁紀錄 page_skus = paginator.page(page_num) except EmptyPage: return http.HttpResponseNotFound('Empty page') # 總頁數 total_pages = paginator.num_pages context = { 'categories': categories, 'breadcrumb': breadcrumb, 'page_skus': page_skus, 'total_page': total_pages, 'page_num': page_num, 'sort': sort, 'category_id': category_id, } return render(request, 'list.html', context)
def get(self, request, sku_id): try: sku = SKU.objects.get(id=sku_id) except SKU.DoesNotExist: return render(request, '404.html') category = sku.category # 获取当前sku所对应的三级分类 # 查询当前sku所对应的spu spu = sku.spu """1.准备当前商品的规格选项列表 [8, 11]""" # 获取出当前正显示的sku商品的规格选项id列表 current_sku_spec_qs = sku.specs.order_by('spec_id') current_sku_option_ids = [] # [8, 11] for current_sku_spec in current_sku_spec_qs: current_sku_option_ids.append(current_sku_spec.option_id) """2.构造规格选择仓库 {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8} """ # 构造规格选择仓库 temp_sku_qs = spu.sku_set.all() # 获取当前spu下的所有sku # 选项仓库大字典 spec_sku_map = { } # {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8} for temp_sku in temp_sku_qs: # 查询每一个sku的规格数据 temp_spec_qs = temp_sku.specs.order_by('spec_id') temp_sku_option_ids = [] # 用来包装每个sku的选项值 for temp_spec in temp_spec_qs: temp_sku_option_ids.append(temp_spec.option_id) spec_sku_map[tuple(temp_sku_option_ids)] = temp_sku.id """3.组合 并找到sku_id 绑定""" spu_spec_qs = spu.specs.order_by('id') # 获取当前spu中的所有规格 for index, spec in enumerate(spu_spec_qs): # 遍历当前所有的规格 spec_option_qs = spec.options.all() # 获取当前规格中的所有选项 temp_option_ids = current_sku_option_ids[:] # 复制一个新的当前显示商品的规格选项列表 for option in spec_option_qs: # 遍历当前规格下的所有选项 temp_option_ids[index] = option.id # [8, 12] option.sku_id = spec_sku_map.get( tuple(temp_option_ids)) # 给每个选项对象绑定下他sku_id属性 spec.spec_options = spec_option_qs # 把规格下的所有选项绑定到规格对象的spec_options属性上 context = { 'categories': get_categories(), # 商品分类 'breadcrumb': get_breadcrumb(category), # 面包屑导航 'sku': sku, # 当前要显示的sku模型对象 'category': category, # 当前的显示sku所属的三级类别 'spu': spu, # sku所属的spu 'spec_qs': spu_spec_qs, # 当前商品的所有规格数据 } return render(request, 'detail.html', context)
def get(self, request, category_id): """ 分类商品数据获取 """ # 1.获取参数并进行校验 page = request.GET.get('page', 1) page_size = request.GET.get('page_size', 10) ordering = request.GET.get('ordering', '-create_time') # 查询数据库获得指定id的商品分类对象 try: cat3 = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return JsonResponse({'code': 400, 'message': '分类数据不存在!'}) # 2.查询获取商品列表页相关数据 # 面包屑导航数据 try: breadcrumb = get_breadcrumb(cat3) except Exception as e: return JsonResponse({'code': 400, 'message': '面包屑导航数据获取错误!'}) # 分类SKU商品数据 try: skus = SKU.objects.filter(category_id=category_id, is_launched=True, ).order_by(ordering) except Exception as e: return JsonResponse({'code': 400, 'message': '分类SKU商品数据获取错误'}) # 3.对SKU商品数据进行分页 paginator = Paginator(skus, page_size) results = paginator.get_page(page) sku_li = [] # FastDFS 中 nginx 服务器的地址 nginx_url = 'http://192.168.19.131:8888/' for sku in results: sku_li.append({ 'id': sku.id, 'name': sku.name, 'price': sku.price, 'comments': sku.comments, 'default_image_url': nginx_url + sku.default_image.name, }) # 4.返回响应数据 return JsonResponse({'code': 0, 'message': 'OK', 'breadcrumb': breadcrumb, 'count': paginator.num_pages, 'list': sku_li, })
def get(self, request, category_id): """提供商品列表页""" # 获取参数: page_num = request.GET.get('page') page_size = request.GET.get('page_size') sort = request.GET.get('ordering') #判断category_id是否正确 try: # 获取三级菜单分类信息: category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return http.JsonResponse({'code': 400, 'errmsg': '获取mysql数据出错'}) #查询面包屑导航 breadcrumb = get_breadcrumb(category) # 排序方式: try: skus = SKU.objects.filter(category=category, is_launched=True).order_by(sort) except SKU.DoesNotExist: return http.JsonResponse({'code': 400, 'errmsg': '获取mysql数据出错'}) paginator = Paginator(skus, 5) # 获取每页商品数据 # 获取每页商品数据 try: page_skus = paginator.page(page_num) except EmptyPage: # 如果page_num不正确,默认给用户400 return http.JsonResponse({'code': 400, 'errmsg': 'page数据出错'}) # 获取列表页总页数 total_page = paginator.num_pages # 定义列表: list = [] # 整理格式: for sku in page_skus: list.append({ 'id': sku.id, 'default_image_url': sku.default_image_url, 'name': sku.name, 'price': sku.price }) # 把数据变为 json 发送给前端 return http.JsonResponse({ 'code': 0, 'errmsg': 'ok', 'breadcrumb': breadcrumb, # 面包屑导航 'list': list, 'count': total_page })
def get(self, request, category_id, page_num): """提供商品列表页""" # 校验参数 # 校验category_id的范围 try: # 三级类别 category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist as e: logger.error(e) return http.HttpResponseForbidden('参数category_id不存在') # 获取sort(排序规则) sort = request.GET.get('sort', 'default') # 根据sort选择排序字段,排序字段必须是模型类的属性 # 按照价格 if sort == 'price': sort_field = 'price' # 按照销量 elif sort == 'hot': sort_field = '-sales' else: # 当出现?sort = xlz sort=default sort = 'default' sort_field = 'create_time' # 查询商品分类 categories = get_categories() # 查询面包屑导航 一级-二级-三级 breadcrumb = get_breadcrumb(category) # 排序category查询sku,一查多 skus = category.sku_set.filter(is_launched=True).order_by(sort_field) # 分页 # 创建分页器 # Paginator('要分页的记录', '每页的条数') paginator = Paginator(skus, settings.HAYSTACK_SEARCH_RESULTS_PER_PAGE) # 获取用户当前要看的那一页(核心) try: page_skus = paginator.page(page_num) except EmptyPage as e: logger.error(e) return http.HttpResponseNotFound('空的页面') # 获取总页数:前端需要使用 total_page = paginator.num_pages # 构造上下文 context = { 'categories': categories, # 频道分类 'breadcrumb': breadcrumb, # 面包屑导航 'page_skus': page_skus, # 分页后数据 'total_page': total_page, # 总页数 'page_num': page_num, # 当前页码 'sort': sort, # 排序字段 'category': category, # 第三级分类 'category_id': category_id # 第三级分类id } return render(request, 'list.html', context)
def get(self, request, category_id, page_num): """提供商品列表页""" try: # 获取三级菜单分类信息: category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return http.HttpResponseNotFound('GoodsCategory 不存在') # 查询商品频道分类 categories = get_categories() # 查询面包屑导航 breadcrumb = get_breadcrumb(category) sort = request.GET.get('sort', 'default') # 按照排序规则查询该分类商品的sku信息 if sort == 'price': # 按照价格由低到高 sortkind = 'price' elif sort == 'hot': # 按照销量由高到低 sortkind = '-sales' else: sort = 'default' sortkind = 'create_time' skus = SKU.objects.filter(category=category, is_launched=True).order_by(sortkind) # 创建分页器:每页N条记录 # # 列表页每页商品数据量 # GOODS_LIST_LIMIT = 5 paginator = Paginator(skus, 5) # 获取每页商品的数据 try: page_skus = paginator.page(page_num) except EmptyPage: # 如果page_num 不正确,默认给用户404 return http.HttpResponseNotFound('empty page') # 获取列表的总页数 total_page = paginator.num_pages # 渲染页面 context = { 'categories': categories, 'breadcrumb': breadcrumb, 'sort': sort, # 排序字段 'category': category, # 第三级分类 'page_skus': page_skus, # 分页后数据 'total_page': total_page, # 总页数 'page_num': page_num, # 当前页码 } return render(request, 'list.html', context)
def get(self, request, category_id, page_num): """ 商品列表页面 :param request: :return: """ # 判断category_id是否正确 try: category = GoodsCategory.objects.get(id=category_id) except Exception as e: logger.error(e) return http.HttpResponseNotFound('category_id 不存在') # 接收sort参数, 用户不传, 就是默认排序 sort = request.GET.get('sort', 'default') # 查询商品分类频道 categories = get_categories() # 查询面包屑导航 breadcrumb = get_breadcrumb(category) # 按照排序规格查询分类的SKU信息 if sort == 'price': sort_field = 'price' elif sort == 'hot': sort_field = '-sales' else: sort = 'default' sort_field = 'create_time' # 分页和排序查询:category查询sku,一查多,一方的模型对象.多方关联字段.all/filter skus = category.sku_set.filter(is_launched=True).order_by(sort_field) # 创建分页器: 每页page_num条记录 paginator = Paginator(skus, constants.GOODS_LIST_LIMIT) try: page_skus = paginator.page(page_num) except EmptyPage: return http.HttpResponseNotFound('empty page') # 获取总页数 total_page = paginator.num_pages # 渲染页面 context = { 'categories': categories, # 频道分类 'breadcrumb': breadcrumb, # 面包屑导航 'sort': sort, # 排序字段 'category': category, # 第三级分类 'page_skus': page_skus, # 分页后数据 'total_page': total_page, # 总页数 'page_num': page_num, # 当前页码 } return render(request, 'list.html', context)
def get(self, request, category_id, page_num): """提供商品列表页""" # 判断category_id是否正确 try: category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return http.HttpResponseNotFound('GoodsCategory does not exist') # 接收sort参数:如果用户不传,就是默认的排序规则 sort = request.GET.get('sort', 'default') # 按照排序规则查询该分类商品SKU信息 if sort == 'price': # 按照价格由低到高 sort_field = 'price' elif sort == 'hot': # 按照销量由高到低 sort_field = '-sales' else: # 'price'和'sales'以外的所有排序方式都归为'default' sort = 'default' sort_field = 'create_time' # 查询商品频道分类 categories = get_categories() # 查询面包屑导航 breadcrumb = get_breadcrumb(category) skus = category.sku_set.filter(is_launched=True).order_by(sort_field) # skus = SKU.objects.filter(category_id=category_id, is_launched=True) # skus = SKU.objects.filter(category=category, is_launched=True).order_by(sort_field) # 创建分页器:每页N条记录 paginator = Paginator(skus, constants.GOODS_LIST_LIMIT) # 获取每页商品数据 try: page_skus = paginator.page(page_num) except EmptyPage: # 如果page_num不正确,默认给用户404 return http.HttpResponseNotFound('empty page') # 获取列表页总页数 total_page = paginator.num_pages # 渲染页面 context = { 'categories': categories, # 频道分类 'breadcrumb': breadcrumb, # 面包屑导航 'sort': sort, # 排序字段 'category': category, # 第三级分类 'page_skus': page_skus, # 分页后数据 'total_page': total_page, # 总页数 'page_num': page_num, # 当前页码 } return render(request, 'list.html', context)
def get(self, request, category_id, page_num): try: cat3 = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return http.HttpResponseForbidden('类别ID不存在') # cat1 = cat3.parent.parent # # 给一级类别定义URL属性 # cat1.url = cat1.goodschannel_set.all()[0].url # # # 包装面包屑导航数据 # breadcrumb = { # 'cat1': cat3.parent.parent, # 'cat2': cat3.parent, # 'cat3': cat3 # } # 获取查询参数中的排序规则 sort = request.GET.get('sort') if sort == 'price': sort_filed = 'price' elif sort == 'hot': sort_filed = 'sales' else: sort = 'default' sort_filed = 'create_time' # 查询指定三级类别下的所有SKU sku_qs = cat3.sku_set.filter(is_launched=True).order_by(sort_filed) # 每页显示5条数据:计算总页数 page = total_count / 5 + (1 if total % 5 else 0) # sa = 5 * (page_num - 1) # sku_qs[sa : (sa + (5 - 1))] # 计算显示指定页的角标 paginator = Paginator(sku_qs, 5) # 创建一个分页对象 try: page_skus = paginator.page(page_num) # 返回指定页的数据 except EmptyPage: return http.HttpResponseForbidden('没有下一页,别点了') total_page = paginator.num_pages # 获取总页数 context = { 'categories': get_categories(), # 频道分类 'breadcrumb': get_breadcrumb(cat3), # 面包屑导航 'sort': sort, # 排序字段 'category': cat3, # 第三级分类 'page_skus': page_skus, # 分页后的数据 'total_page': total_page, # 总页数 'page_num': page_num # 当前页码 } return render(request, 'list.html', context)
def get(self, request, sku_id): try: sku = SKU.objects.get(id=sku_id) except SKU.DoesNotExist: return render(request, "404.html") category = sku.category spu = sku.spu """1 准备当前商品的规格选项列表""" # 获取出当前正在显示的sku商品的规格选项Id列表 current_sku_spec_qs = sku.specs.order_by("spec_id") current_sku_options_ids = [] for current_sku_spec in current_sku_spec_qs: current_sku_options_ids.append(current_sku_spec.option_id) """2 构造规则选择仓库 {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8} """ # 构造规格选择仓库 temp_sku_qs = spu.sku_set.all() # 选项仓库大字典 spec_sku_map = {} for temp_sku in temp_sku_qs: temp_spec_qs = temp_sku.specs.order_by("spec_id") temp_sku_option_ids = [] for temp_spec in temp_spec_qs: temp_sku_option_ids.append(temp_spec.option_id) spec_sku_map[tuple(temp_sku_option_ids)] = temp_sku.id """3 组合 并找到sku_id 绑定""" spu_spec_qs = spu.specs.order_by("id") for index, spec in enumerate(spu_spec_qs): spec_option_qs = spec.options.all() temp_option_ids = current_sku_options_ids[:] for option in spec_option_qs: temp_option_ids[index] = option.id option.sku_id = spec_sku_map.get(tuple(temp_option_ids)) spec.spec_options = spec_option_qs category = sku.category context = { "categories": get_categories(), # 商品分类 "breadcrumb": get_breadcrumb(category), # 面包屑导航 "sku": sku, # 当前要显示的sku模型对象 "spu": sku.spu, # sku所属的spu "category": category, # 当前的显示sku所属的三级列别 "spec_qs": spu_spec_qs, # 当前商品的所有规格数据 } return render(request, "detail.html", context)
def get(self, request ,sku_id ): """提供商品詳情頁面""" #接收並校驗參數 try: sku = SKU.objects.get(id=sku_id, is_launched=True) except Exception: return render(request, '404.html') #查詢商品分類 categories = get_categories() #查詢麵包屑導航 breadcrumb = get_breadcrumb(sku.category) #查詢當前商品規格 goods = sku.goods #建立當前商品規格鍵 sku_specs = sku.skuspecification_set.order_by('spec_id') sku_key = [] # [規格1,規格2,..] for spec in sku_specs: sku_key.append(spec.option_id) #取出當前商品所有規格鍵和對應sku_id建立字典 skus = sku.goods.sku_set.all() key_sku_map = {} for s in skus: s_specs = s.skuspecification_set.order_by('spec_id') key = [] for spec in s_specs: key.append(spec.option_id) key_sku_map[tuple(key)] = s.id # {(規格1,規格2,..):sku_id,..) #獲取當前商品規格對象 goods_specs = goods.goodsspecification_set.order_by('id') for index, spec in enumerate(goods_specs): #複製當前規格鍵 key = sku_key[:] options = spec.specificationoption_set.all() for option in options: #查出當前商品對應的規格對象 key[index] = option.id #從字典找出sku_id賦值 option.sku_id = key_sku_map.get(tuple(key)) spec.spec_options = options #網頁訪問不須登入,所以設置csrftoken get_token(request) #構造響應數據 context = { 'categories':categories , 'breadcrumb':breadcrumb , 'sku':sku , 'specs':goods_specs , 'category_id':sku.category.id , } return render(request ,'detail.html' ,context )
def get(self, request, category_id, page_num): """ 展示商品列表详情页 :param request: :return: """ # 获取参数 sort = request.GET.get('sort', 'default') # 校验参数 # 路由里面已经进行过正则匹配了 # if not all([category_id, page_num]): # return http.HttpResponseForbidden('缺少必传参数') try: # 根据商品id获取商品列表并排序 category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return http.HttpResponseNotFound('GoodCategory 不存在') # 获取商品类别 categories = get_categories() # 根据商品类别id获取商品导航页 breadcrumb = get_breadcrumb(category) # 根据sort的内容确定排序的方式 if sort == 'price': sort_kind = 'price' elif sort == 'hot': sort_kind = '-sales' else: sort_kind = 'create_time' sku_s = category.sku_set.filter(is_launched=True).order_by(sort_kind) # 创建分页对象 paginator = Paginator(sku_s, 5) # 根据页数返回页面的数据 try: content = paginator.page(page_num) except EmptyPage: return http.HttpResponseNotFound('页面不存在') # 返回总页数 page_nums = paginator.num_pages # 拼接数据进行返回 context = { 'categories': categories, 'breadcrumb': breadcrumb, 'sort': sort, 'category': category, 'page_skus': sku_s, 'total_page': page_nums, 'page_num': page_num } return render(request, 'list.html', context=context)
def generate_static_sku_detail_html(sku_id): """批量生成商品詳情頁靜態頁面""" #獲取SKU sku = SKU.objects.get(id=sku_id, is_launched=True) #查詢商品分類 categories = get_categories() #查詢麵包屑導航 breadcrumb = get_breadcrumb(sku.category) #查詢當前商品規格 goods = sku.goods #建立當前商品規格鍵 sku_specs = sku.skuspecification_set.order_by('spec_id') sku_key = [] #[規格1,規格2,..] for spec in sku_specs: sku_key.append(spec.option_id) #取出當前商品所有規格鍵和對應sku_id建立字典 skus = sku.goods.sku_set.all() key_sku_map = {} for s in skus: s_specs = s.skuspecification_set.order_by('spec_id') key = [] for spec in s_specs: key.append(spec.option_id) key_sku_map[tuple(key)] = s.id # {(規格1,規格2,..):sku_id,..) #獲取當前商品規格對象 goods_specs = goods.goodsspecification_set.order_by('id') for index, spec in enumerate(goods_specs): #複製當前規格鍵 key = sku_key[:] options = spec.specificationoption_set.all() for option in options: #查出當前商品對應的規格對象 key[index] = option.id #從字典找出sku_id賦值 option.sku_id = key_sku_map.get(tuple(key)) spec.spec_options = options #構造響應數據 context = { 'categories': categories, 'breadcrumb': breadcrumb, 'sku': sku, 'specs': goods_specs, 'category_id': sku.category.id, } template = loader.get_template('detail.html') html_text = template.render(context) file_path = os.path.join(settings.STATICFILES_DIRS[0], 'details/' + str(sku_id) + '.html') with open(file_path, 'w') as f: f.write(html_text)
def get(self, request, category_id, page_num): """提供商品列表页""" # 1.校验category_id try: # 获取三级菜单分类信息 category = GoodsCategory.objects.get(id=category_id) except GoodsCategory.DoesNotExist: return http.HttpResponseNotFound('GoodsCategory不存在') # 2.获取商品频道分类 categories = get_categories() # 3.获取面包屑导航 breadcrumb = get_breadcrumb(category) # 4.获取前端用查询字符串方式传来的sort参数,如没有,则取默认值default sort = request.GET.get('sort', 'default') # 5.判断排序方式,确认排序依据 if sort == 'price': # 按照价格由低到高排序 sortkind = 'price' elif sort == 'hot': # 按照销量由高到低排序 sortkind = '-sales' else: sort = 'default' # 默认排序,按照创建时间排序 sortkind = 'create_time' # 6.获取当前分类并且上架的商品,并对商品按照上面的排序方式进行排序 skus = SKU.objects.filter(category=category, is_launched=True).order_by(sortkind) # 7.创建一个分页器对象,第一个参数为要展示的数据列表,第二个参数为每页的显示数量 paginator = Paginator(skus, 5) # 8.获取对应页面的商品 try: page_skus = paginator.page(page_num) # 如果只有四页数据,但是前端索求第五页的数据,则报错 except EmptyPage: return http.HttpResponseNotFound('Empty Page') # 9.获取总页数 total_page = paginator.num_pages # 10.拼接数据字典 context = { 'categories': categories, # 频道分类 'breadcrumb': breadcrumb, # 面包屑导航 'sort': sort, # 排序字段 'category': category, # 第三级分类 'page_skus': page_skus, # 对应页面的商品 'total_page': total_page, # 总页数 'page_num': page_num # 当前页码 } # 11.渲染页面 return render(request, 'list.html', context)