034、性能优化--页面静态化

    xiaoxiao2023-11-27  166

    思考:

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

    问题:

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

    解决:

    页面静态化

    1. 页面静态化介绍

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

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

    2.什么是页面静态化

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

    3.页面静态化注意点

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

    2. 首页页面静态化实现

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

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

    2.首页页面静态化实现

    def generate_static_index_html(): """ 生成静态的主页html文件 """ print('%s: generate_static_index_html' % time.ctime()) # 获取商品频道和分类 categories = get_categories() # 广告内容 contents = {} content_categories = ContentCategory.objects.all() for cat in content_categories: contents[cat.key] = cat.content_set.filter(status=True).order_by('sequence') # 渲染模板 context = { 'categories': categories, 'contents': contents } # 获取首页模板文件 template = loader.get_template('index.html') # 渲染首页html字符串 html_text = template.render(context) # 将首页html字符串写入到指定目录,命名'index.html' 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)

    3.首页页面静态化测试效果

    3. 定时任务crontab静态化首页

    重要提示:

    对于首页的静态化,考虑到页面的数据可能由多名运营人员维护,并且经常变动,所以将其做成定时任务,即定时执行静态化。在Django执行定时任务,可以通过django-crontab扩展来实现。

    1.安装 django-crontab

    $ pip install django-crontab

    2.注册 django-crontab 应用

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

    3.设置定时任务

    定时时间基本格式 : * * * * * 分 时 日 月 周 命令 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'

    4.管理定时任务

    # 添加定时任务到系统中 $ python manage.py crontab add # 显示已激活的定时任务 $ python manage.py crontab show # 移除定时任务 $ python manage.py crontab remove

    3、批量静态化详情页

    提示:

    商品详情页查询数据量大,而且是用户频繁访问的页面。类似首页广告,为了减少数据库查询次数,提升页面响应效率,我们也要对详情页进行静态化处理。

    静态化说明:

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

    注意:

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

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

    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'] = 'meiduo_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'] = 'meiduo_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)

    2. 执行批量静态化详情页脚本文件

    1.添加Python脚本文件可执行权限

    $ chmod +x regenerate_detail_html.py

    2.执行批量静态化详情页脚本文件

    $ cd ~/projects/meiduo_project/meiduo_mall/scripts

    $ ./regenerate_detail_html.py

    提示:跟测试静态首页一样的,使用Python自带的http.server模块来模拟静态服务器,提供静态首页的访问测试。

    # 进入到static上级目录 $ cd ~/projects/meiduo_project/meiduo_mall/meiduo_mall # 开启测试静态服务器 $ python -m http.server 8080 --bind 127.0.0.1

    最新回复(0)