python学习之美多商城(十五):商品部分:商品列表页、分类数据静态化、获取商品列表数据

版权声明:浅弋、璃鱼的原创 https://blog.csdn.net/qq_35709559/article/details/86592903

一、商品列表页

在这里插入图片描述
当用户访问网址/list.html?cat=xxx时, 会进入商品列表页。网址中的cat参数是用于过滤商品数据的第三季商品类别,也就是在商品列表中会根据cat参数筛选商品数据用于展示。

1.商品列表页逻辑分析:

  • 静态逻辑:商品分类数据展示(需要提前做静态化处理)
  • 动态逻辑:商品面包屑导航数据和商品列表数据

二、商品分类数据静态化:

  • 商品列表页中商品分类数据依然采用页面静态化技术展示。
  • 商品列表页中商品分类数据的静态化由运营人员在编辑商品分类信息时触发生成静态化页面。
  • 商品列表页中商品分类数据的页面静态化处理,我们选择使用异步任务类执行。

1.准备静态化异步任务:

  • 在goods/utils.py中封装方法,获取商品分类菜单数据:
#meiduo_mall/apps/goods/utils.py
# -*-coding:utf-8-*-
from collections import OrderedDict

from goods.models import GoodsChannel


def get_categories():
    """
    获取商品分类菜单
    :return: 
    """

    # 商品频道及分类菜单
    # 使用有序字典保存类别的顺序
    # categories = {
    #     1: { # 组1
    #         'channels': [{'id':, 'name':, 'url':},{}, {}...],
    #         'sub_cats': [{'id':, 'name':, 'sub_cats':[{},{}]}, {}, {}, ..]
    #     },
    #     2: { # 组2
    #
    #     }
    # }
    categories = OrderedDict()
    channels = GoodsChannel.objects.order_by('group_id', 'sequence')
    for channel in channels:
        group_id = channel.group_id  # 当前组

        if group_id not in categories:
            categories[group_id] = {'channels': [], 'sub_cats': []}

        cat1 = channel.category  # 当前频道的类别

        # 追加当前频道
        categories[group_id]['channels'].append({
            'id': cat1.id,
            'name': cat1.name,
            'url': channel.url
        })
        # 构建当前类别的子类别
        for cat2 in cat1.goodscategory_set.all():
            cat2.sub_cats = []
            for cat3 in cat2.goodscategory_set.all():
                cat2.sub_cats.append(cat3)
            categories[group_id]['sub_cats'].append(cat2)
     return categories
  • 在celery_tasks中新建html/tasks.py任务:
# celery_tasks/html.tasks.py

# -*-coding:utf-8-*-
import os
from celery.contrib.pytest import celery_app
from django.conf import settings
from django.template import loader

from goods.utils import get_categories


@ celery_app.tasks(name='generate_static_list_search_html')
def generate_static_list_search_html():
    """
    生成静态的商品列表页和搜索结果页html文件
    :return:
    """
    # 商品分类菜单
    categories = get_categories()

    # 渲染模板,生成静态文件
    context = {
        'categories':categories
    }
    template = loader.get_template('list.html')
    html_text = template.render(context)
    file_path = os.path.join(settings.GENERATED_STATIC_HTML_FILES_DIR, 'list.html')
    with open(file_path, 'w') as f:
        f.write(html_text)

2.运营人员站点中触发异步任务:

  • 在goods/admin.py中,展示模型类数据,并触发异步任务
# meiduo_mall/apps/goods/admin.py

from django.contrib import admin
# Register your models here.
from goods.models import GoodsCategory, Brand, Goods, SKU, GoodsChannel, GoodsSpecification, SpecificationOption, \
    SKUSpecification, SKUImage


class GoodsCategoryAdmin(admin.ModelAdmin):

    def save_model(self, request, obj, form, change):
        obj.save()
        from celery_tasks.html.tasks import generate_static_list_search_html
        generate_static_list_search_html.delay()

    def delete_model(self, request, obj):
        obj.delete()
        from celery_tasks.html.tasks import generate_static_list_search_html
        generate_static_list_search_html.delay()


admin.site.register(GoodsCategory, GoodsCategoryAdmin)
admin.site.register(GoodsChannel)
admin.site.register(Goods)
admin.site.register(Brand)
admin.site.register(GoodsSpecification)
admin.site.register(SpecificationOption)
admin.site.register(SKU)
admin.site.register(SKUSpecification)
admin.site.register(SKUImage)

三、获取商品列表数据:

业务需求:

  • 商品列表数据分页处理,并且可以按照创建时间(默认)、价格、销量(人气)进行排序。

1.商品列表数据分页和排序处理

1.1 后端接口设计:

请求方式: GET  /categories/(?P<category_id>\d+)/skus/?page= <; int:page>&page_size=<int:page_size>&ordering=<str:ordering>
请求参数: 路径传参, 查询字符串

参数名 类型 是否必须 说明
category_id int 商品分类id(第三级)
page int 请求页数
page_size int 每页数量
ordering str 排序关键字(‘create_time’, ‘price’, ‘sales’)

返回数据: JSON

{
    "count": 14,
    "next": "http://api.meiduo.site:8000/categories/115/skus/?page=2",
    "previous": null,
    "results": [
        {
            "id": 3,
            "name": "Apple iPhone 8 Plus (A1864) 64GB 金色 移动联通电信4G手机",
            "price": "6499.00",
            "default_image_url": "http://image.meiduo.site:8888/group1/M00/00/02/CtM3BVrRZCqAUxp9AAFti6upbx41220032",
            "comments": 0
        },
        {
            "id": 4,
            "name": "Apple iPhone 8 Plus (A1864) 256GB 金色 移动联通电信4G手机",
            "price": "7988.00",
            "default_image_url": "http://image.meiduo.site:8888/group1/M00/00/02/CtM3BVrRZa6ANO_sAAFti6upbx40753757",
            "comments": 0
        }
    ]
}
返回值 类型 是否必须 说明
count int
next url 下一页的链接地址
previous url 上一页的链接地址
results sku[] 商品sku数据列表
id int 商品sku 编号
name str 商品名称
price decimal 单价
default_image_url str 默认图片
comments int 评论量

1.2 后端实现:

在meiduo_mall/utils中创建pagination.py文件,并在其中创建分页配置类:

# meiduo_mall/utils/pagination.py

# -*-coding:utf-8-*-
from rest_framework.pagination import PageNumberPagination

class StandardResultsSetPagination(PageNumberPagination):
    page_size = 2
    page_size_query_param = 'page_size'
    max_page_size = 20

在配置文件中设置REST framework分页使用的分页类:

# meiduo_mall/settings/dev.py

REST_FRAMEWORK = {
    ...
    # 分页
    'DEFAULT_PAGINATION_CLASS': 'meiduo_mall.utils.pagination.StandardResultsSetPagination',
}

定义序列化器

# meiduo_mall/apps/goods/serializers.py
# -*-coding:utf-8-*-
from rest_framework import serializers
from goods.models import SKU


class CategoriesListSerializer(serializers.ModelSerializer):
    """列表页序列化器"""
    # create_time = serializers.DateField(read_only=True)
    # update_time = serializers.DateField(read_only=True)

    class Meta:
        model = SKU
        fields = "__all__"

在goods/views.py中实现视图:

# meiduo_mall/apps/goods/views.py

from django.shortcuts import render

# Create your views here.
from rest_framework.filters import OrderingFilter
from rest_framework.generics import ListAPIView

from goods.models import SKU
from goods.serializers import CategoriesListSerializer


class SKUListView(ListAPIView):
    """
    sku列表数据
    """
    serializer_class = CategoriesListSerializer
    
    # 分页与排序
    filter_backends = (OrderingFilter,)
    ordering_fields = ('create_time', 'price', 'sales')
    
    def get_queryset(self):
        """
        获取查询集
        :return: 
        """
        return SKU.objects.filter(category_id=self.kwargs["pk"])

说明:
REST framework提供了对于排序的支持,使用REST framework提供的OrderingFilter过滤器后端即可。

OrderingFilter过滤器要使用ordering_fields 属性来指明可以进行排序的字段有哪些。
注册路由:

# meiduo_mall/apps/goods/urls.py

# -*-coding:utf-8-*-
from django.conf.urls import url

from goods import views

urlpatterns = [
    url(r"^categories/(?P<pk>\d+)/skus/$",views.SKUListView.as_view()),
]

猜你喜欢

转载自blog.csdn.net/qq_35709559/article/details/86592903