二十五、详情页静态页面的生成(商品部分)

商品详情页依然采用页面静态化技术。
商品详情页的静态化由运营人员在编辑商品信息时触发生成静态化页面。

1、实现静态化异步任务

<1>在celery_tasks中新建statics/tasks.py任务

from celery_tasks.main import app
from django.template import loader
from django.conf import settings
import os

from goods.utils import get_categories
from goods.models import SKU


@app.task(name='generate_static_sku_detail_html')
def generate_static_sku_detail_html(sku_id):
    """
    生成静态商品详情页面
    :param sku_id: 商品sku id
    """
    # 商品分类菜单
    categories = get_categories()

    # 获取当前sku的信息
    sku = SKU.objects.get(id=sku_id)
    sku.images = sku.skuimage_set.all()

    # 面包屑导航信息中的频道
    goods = sku.goods
    goods.channel = goods.category1.goodschannel_set.all()[0]

    # 构建当前商品的规格键
    # sku_key = [规格1参数id, 规格2参数id, 规格3参数id, ...]
    sku_specs = sku.skuspecification_set.order_by('spec_id')
    sku_key = []
    for spec in sku_specs:
        sku_key.append(spec.option.id)

    # 获取当前商品的所有SKU
    skus = goods.sku_set.all()

    # 构建不同规格参数(选项)的sku字典
    # spec_sku_map = {
    #     (规格1参数id, 规格2参数id, 规格3参数id, ...): sku_id,
    #     (规格1参数id, 规格2参数id, 规格3参数id, ...): sku_id,
    #     ...
    # }
    spec_sku_map = {}
    for s in skus:
        # 获取sku的规格参数
        s_specs = s.skuspecification_set.order_by('spec_id')
        # 用于形成规格参数-sku字典的键
        key = []
        for spec in s_specs:
            key.append(spec.option.id)
        # 向规格参数-sku字典添加记录
        spec_sku_map[tuple(key)] = s.id

    # 获取当前商品的规格信息
    #specs = [
    #    {
    #        'name': '屏幕尺寸',
    #        'options': [
    #            {'value': '13.3寸', 'sku_id': xxx},
    #            {'value': '15.4寸', 'sku_id': xxx},
    #        ]
    #    },
    #    {
    #        'name': '颜色',
    #        'options': [
    #            {'value': '银色', 'sku_id': xxx},
    #            {'value': '黑色', 'sku_id': xxx}
    #        ]
    #    },
    #    ...
    #]
    specs = goods.goodsspecification_set.order_by('id')
    # 若当前sku的规格信息不完整,则不再继续
    if len(sku_key) < len(specs):
        return
    for index, spec in enumerate(specs):
        # 复制当前sku的规格键
        key = sku_key[:]
        # 该规格的选项
        options = spec.specificationoption_set.all()
        for option in options:
            # 在规格参数sku字典中查找符合当前规格的sku
            key[index] = option.id
            option.sku_id = spec_sku_map.get(tuple(key))

        spec.options = options

    # 渲染模板,生成静态html文件
    context = {
        'categories': categories,
        'goods': goods,
        'specs': specs,
        'sku': sku
    }

    template = loader.get_template('detail.html')
    html_text = template.render(context)
    file_path = os.path.join(os.path.dirname(os.path.dirname(settings.BASE_DIR)), 'front_end_pc/goods/'+str(sku_id)+'.html')
    with open(file_path, 'w') as f:
        f.write(html_text)

<2>异步任务的触发

1>运营人员在Admin站点保存商品信息时,应该触发生成商品静态页的异步任务。
2>我们需要调整Admin站点保存和删除商品信息时行为。
3>在Admin站点保存或删除数据时,Django是调用的Admin站点管理器类的save_model()方法和delete_model()方法,我们只需重新实现这两个方法,在这两个方法中调用异步任务即可。

编辑goods/admin.py

from celery_tasks.static_html.tasks import  generate_static_sku_detail_html
...

class SKUAdmin(admin.ModelAdmin):

    def save_model(self, request, obj, form, change):
        obj.save()
        generate_static_sku_detail_html.delay(obj.id)
...        
admin.site.register(models.SKU,SKUAdmin)

2、借助shell工具生成商品详情静态页面

# 在终端进入shell中
python manage.py shell 
from goods.models import SKU
skus=SKU.objects.all()
from celery_tasks.static_html.tasks improt generate_static_sku_detail_html 
for sku in skus:
	generate_static_sku_detail_html.delay(sku.id)

你可能感兴趣的:(django项目--电商网站)