Python项目实战 10.1:性能优化:页面静态化

目录

一、首页广告页面静态化

二、商品详情页面静态化


一、首页广告页面静态化

思考:

  • 美多商城的首页访问频繁,而且查询数据量大,其中还有大量的循环处理。

问题:

  • 用户访问首页会耗费服务器大量的资源,并且响应数据的效率会大大降低。

解决:

  • 页面静态化

关于页面静态化

1. 为什么要做页面静态化

  • 减少数据库查询次数。
  • 提升页面响应效率。

2. 什么是页面静态化

  • 将动态渲染生成的页面结果保存成html文件,放到静态文件服务器中。
  • 用户直接去静态服务器,访问处理好的静态html文件。

3. 页面静态化注意点

  • 用户相关数据不能静态化:用户名、购物车等不能静态化。
  • 动态变化的数据不能静态化:热销排行、新品推荐、分页排序数据等等。
  • 不能静态化的数据处理:
    • 可以在用户得到页面后,在页面中向后端发送Ajax请求获取相关数据。
    • 直接使用模板渲染出来。
    • 其他合理的处理方式等等。

首页页面静态化实现 

1. 首页页面静态化实现步骤

  • 查询首页相关数据
  • 获取首页模板文件
  • 渲染首页html字符串
  • 将首页html字符串写入到指定目录,命名'index.html'

2. 首页页面静态化实现

crons.py:

# 静态化首页
from collections import OrderedDict
from django.template import loader
import os
from django.conf import settings

from contents.utils import get_categories
from contents.models import ContentCategory


def generate_static_index_html():
    """静态化首页"""
    # 查询并展示商品分类
    categories = get_categories()

    # 查询首页广告数据
    contents = OrderedDict()
    content_categories = ContentCategory.objects.all()
    for content_category in content_categories:
        # 使用广告类别查询出该类别对应的所有的广告内容
        contents[content_category.key] = content_category.content_set.filter(status=True).order_by(
            'sequence')  # 查询出未下架的广告并排序

    # 构造上下文
    context = {
        'categories': categories,
        'contents': contents
    }

    # 渲染模板
    # 先获取模板文件
    template = loader.get_template('index.html')
    # 在使用上下文渲染模板文件
    html_text = template.render(context)

    # 将模板文件写入到静态路径
    file_path = os.path.join(settings.STATICFILES_DIRS[0], 'index.html')
    with open(file_path, 'w', encoding='utf-8') as f:
        f.write(html_text)

定时任务crontab静态化首页

Django执行定时任务,可以通过django-crontab扩展来实现。

pip install django-crontab

dev.py配置文件中注册 django-crontab 应用

INSTALLED_APPS = [    
    'django_crontab', # 定时任务
]

设置定时任务

定时时间基本格式 :

*  *  *  *  *

分 时 日 月 周    命令

M: 分钟(0-59)。每分钟用 * 或者 */1 表示
H:小时(0-23)。(0表示0点)
D:天(1-31)。
m: 月(1-12)。
d: 一星期内的天(0~6,0为星期天)。

定时任务分为三部分定义:

  • 任务时间
  • 任务方法
  • 任务日志
CRONJOBS = [
    # 每1分钟生成一次首页静态文件
    ('*/1 * * * *', 'contents.crons.generate_static_index_html', '>> ' + os.path.join(os.path.dirname(BASE_DIR), 'logs/crontab.log'))
]

解决 crontab 中文问题

  • 在定时任务中,如果出现非英文字符,会出现字符异常错误
CRONTAB_COMMAND_PREFIX = 'LANG_ALL=zh_cn.UTF-8'

管理定时任务

# 添加定时任务到系统中
$ python manage.py crontab add

# 显示已激活的定时任务
$ python manage.py crontab show

# 移除定时任务
$ python manage.py crontab remove

 

二、商品详情页面静态化

  • 商品详情页查询数据量大,而且是用户频繁访问的页面。
  • 类似首页广告,为了减少数据库查询次数,提升页面响应效率,我们也要对详情页进行静态化处理。
  • 首页广告的数据变化非常的频繁,所以我们最终使用了定时任务进行静态化。
  • 详情页的数据变化的频率没有首页广告那么频繁,而且是当SKU信息有改变时才要更新的,所以我们采用新的静态化方案。
    • 方案一:通过Python脚本手动一次性批量生成所有商品静态详情页。
    • 方案二:后台运营人员修改了SKU信息时,异步的静态化对应的商品详情页面。
    • 我们在这里先使用方案一来静态详情页。当有运营人员参与时才会补充方案二。

注意:

  • 用户数据和购物车数据不能静态化。
  • 热销排行和商品评价不能静态化。

 定义批量静态化详情页脚本文件

1. 新建脚本目录和Python脚本文件

 

2. 指定Python脚本解析器

#!/usr/bin/env python

3. 添加Python脚本导包路径

#!/usr/bin/env python

import sys
sys.path.insert(0, '../')

4. 设置Python脚本Django环境

#!/usr/bin/env python

import sys
sys.path.insert(0, '../')

import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'wangye_mall.settings.dev'

import django
django.setup()

5. 编写静态化详情页Python脚本代码

#!/usr/bin/env python

import sys
sys.path.insert(0, '../')

import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'wangye_mall.settings.dev'

import django
django.setup()

from django.template import loader
from django.conf import settings

from goods import models
from contents.utils import get_categories
from goods.utils import get_breadcrumb


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)

if __name__ == '__main__':
    skus = models.SKU.objects.all()
    for sku in skus:
        print(sku.id)
        generate_static_sku_detail_html(sku.id)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值