Django页面静态化的流程

引子

在工作中接盘,遇到商城的首页被频繁访问(频繁查询数据库)导致宕机,但首页数据变动频率较低,如果通过静态html展示那么在访问速度会有很大的提升,并且对seo有很大帮助.

理解

页面静态化即将动态渲染生成的页面结果保存成html文件,放到静态文件服务器中。用户访问的时候访问的直接是处理好之后的html静态文件
对于页面中属于每个用户展示不同数据内容的部分,可以在用户请求完静态化之后的页面后,在页面中向后端发送请求,获取属于用户的特殊的数据

用到的库

django-crontab
  
  
  • 1

大体流程

准备页面静态化(模板渲染脚本)
V
配置渲染的静态页面存储位置
V
确认需要静态化的模板,进行Vue模板语法的处理
V
准备静态化脚本
V
设置定时任务
V
启动


代码(Django框架下)

新建crons.py 存储页面静态化逻辑

import time
import os
from goods.models import GoodsChannel
from .models import ContentCategory
from collections import OrderedDict
from django.template import loader
from django.conf import settings



def generate_static_index_html():
    """
    生成静态的主页html
    """

    print('%s:generate_static_index' % time.ctime())
    # 商品频道及分类菜单
    # 使用有序字典保存类别的顺序
    # 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
        group_id = channel.group_id
        # 判断group_id 是否在存储容器,如果不在就初始化
        if group_id not in categories:
            categories[group_id] = {
                'channels': [],
                'sub_cats': []
            }

        one = channel.category
        # 为channels填充数据
        categories[group_id]['channels'].append({
            'id': one.id,
            'name': one.name,
            'url': channel.url
        })
        # 为sub_cats填充数据
        for two in one.goodscategory_set.all():
            # 初始化 容器
            two.sub_cats = []
            # 遍历获取
            for three in two.goodscategory_set.all():
                two.sub_cats.append(three)

            # 组织数据
            categories[group_id]['sub_cats'].append(two)

    # 广告和首页数据
    contents = {}
    content_categories = ContentCategory.objects.all()
    # content_categories = [{'name':xx , 'key': 'index_new'}, {}, {}]
    # {
    #    'index_new': [] ,
    #    'index_lbt': []
    # }
    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_data = template.render(context)

    #将文件写入
    file_path = os.path.join(settings.GENERATED_STATIC_HTML_FILES_DIR,'index.html')
    with open(file_path,'w') as f:
        f.write(html_data)
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

配置settings

# 生成的静态html文件保存目录
GENERATED_STATIC_HTML_FILES_DIR = os.path.join(os.path.dirname(BASE_DIR), 'front')
  
  
  • 1
  • 2

在工程目录中新建templates模板目录

在模板目录中新建index.html模板文件,copy模板代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>******商城-首页</title>
    <link rel="stylesheet" type="text/css" href="css/reset.css">
    <link rel="stylesheet" type="text/css" href="css/main.css">
    <script type="text/javascript" src="js/host.js"></script>
    <script type="text/javascript" src="js/vue-2.5.16.js"></script>
    <script type="text/javascript" src="js/axios-0.18.0.min.js"></script>
    <script type="text/javascript" src="js/jquery-1.12.4.min.js"></script>
    <script type="text/javascript" src="js/slide.js"></script>
</head>
<body>
    <div id="app" v-cloak>
    <div class="header_con">
        <div class="header">
            <div class="welcome fl">欢迎来到*****商城!</div>
            <div class="fr">
                <div v-if="username" class="login_btn fl">
                    欢迎您:<em>[[ username ]]</em>
                    <span>|</span>
                    <a @click="logout">退出</a>
                </div>
                <div v-else class="login_btn fl">
                    <a href="login.html">登录</a>
                    <span>|</span>
                    <a href="register.html">注册</a>
                </div>
                <div class="user_link fl">
                    <span>|</span>
                    <a href="user_center_info.html">用户中心</a>
                    <span>|</span>
                    <a href="cart.html">我的购物车</a>
                    <span>|</span>
                    <a href="user_center_order.html">我的订单</a>
                </div>
            </div>
        </div>
    </div>

    <div class="search_bar clearfix">
        <a href="index.html" class="logo fl"><img src="images/logo.png"></a>
        <div class="search_wrap fl">
            <form method="get" action="/search.html" class="search_con">
                <input type="text" class="input_text fl" name="q" placeholder="搜索商品">
                <input type="submit" class="input_btn fr" name="" value="搜索">
            </form>
            <ul class="search_suggest fl">
                <li><a href="#">索尼微单</a></li>
                <li><a href="#">优惠15元</a></li>
                <li><a href="#">美妆个护</a></li>
                <li><a href="#">买2免1</a></li>
            </ul>
        </div>

        <div class="guest_cart fr">
            <a href="#" class="cart_name fl">我的购物车</a>
            <div class="goods_count fl" id="show_count">15</div>

            <ul class="cart_goods_show">
                <li>
                    <img src="images/goods/goods001.jpg" alt="商品图片">
                    <h4>商品名称手机</h4>
                    <div>4</div>
                </li>
                <li>
                    <img src="images/goods/goods002.jpg" alt="商品图片">
                    <h4>商品名称手机</h4>
                    <div>5</div>
                </li>
                <li>
                    <img src="images/goods/goods003.jpg" alt="商品图片">
                    <h4>商品名称手机</h4>
                    <div>6</div>
                </li>
                <li>
                    <img src="images/goods/goods003.jpg" alt="商品图片">
                    <h4>商品名称手机</h4>
                    <div>6</div>
                </li>
            </ul>
        </div>
    </div>

    <div class="navbar_con">
        <div class="navbar">
            <h1 class="fl">商品分类</h1>
            <ul class="navlist fl">
                <li><a href="">首页</a></li>
                <li class="interval">|</li>
                <li><a href="">真划算</a></li>
                <li class="interval">|</li>
                <li><a href="">抽奖</a></li>
            </ul>
        </div>
    </div>

    <div class="pos_center_con clearfix">
        <ul class="slide">
            {% for content in contents.index_lbt %}
            <li><a href="{{ content.url }}"><img src="{{ content.image.url }}" alt="{{ content.title }}"></a></li>
            {% endfor %}
        </ul>
        <div class="prev"></div>
        <div class="next"></div>
        <ul class="points">
            <!-- <li class="active"></li>
            <li></li>
            <li></li>
            <li></li> -->
        </ul>
        <ul class="sub_menu">
            {% for group in categories.values %}
            <li>
                <div class="level1">
                    {% for channel in group.channels %}
                    <a href="{{ channel.url }}">{{ channel.name }}</a>
                    {% endfor %}
                </div>
                <div class="level2">
                    {% for cat2 in group.sub_cats %}
                    <div class="list_group">
                        <div class="group_name fl">{{cat2.name}} &gt;</div>
                        <div class="group_detail fl">
                            {% for cat3 in cat2.sub_cats %}
                            <a href="/list.html?cat={{cat3.id}}">{{cat3.name}}</a>
                            {% endfor %}
                        </div>
                    </div>
                    {% endfor %}
                </div>
            </li>
            {% endfor %}
        </ul>

        <div class="news">
            <div class="news_title">
                <h3>快讯</h3>
                <a href="#">更多 &gt;</a>
            </div>
            <ul class="news_list">
                {% for content in contents.index_kx %}
                <li><a href="{{ content.url }}">{{ content.title }}</a></li>
                {% endfor %}
            </ul>
            {% for content in contents.index_ytgg %}
            <a href="{{ content.url }}" class="advs"><img src="{{ content.image.url }}"></a>
            {% endfor %}
        </div>
    </div>

    <div class="list_model">
        <div class="list_title clearfix">
            <h3 class="fl" id="model01">1F 手机通讯</h3>
            <div class="subtitle fr">
                <a @mouseenter="f1_tab=1" :class="f1_tab===1?'active':''">时尚新品</a>
                <a @mouseenter="f1_tab=2" :class="f1_tab===2?'active':''">畅想低价</a>
                <a @mouseenter="f1_tab=3" :class="f1_tab===3?'active':''">手机配件</a>
            </div>
        </div>
        <div class="goods_con clearfix">
            <div class="goods_banner fl">
                <img src="{{ contents.index_1f_logo.0.image.url }}">
                <div class="channel">
                    {% for content in contents.index_1f_pd %}
                    <a href="{{ content.url }}">{{ content.title }}</a>
                    {% endfor %}
                </div>
                <div class="key_words">
                    {% for content in contents.index_1f_bq %}
                    <a href="{{ content.url }}">{{ content.title }}</a>
                    {% endfor %}
                </div>

            </div>
            <ul v-show="f1_tab===1" class="goods_list fl">
                {% for content in contents.index_1f_ssxp %}
                <li>
                    <a href="{{ content.url }}" class="goods_pic"><img src="{{ content.image.url }}"></a>
                    <h4><a href="{{ content.url }}" title="{{ content.title }}">{{ content.title }}</a></h4>
                    <div class="prize">{{ content.text }}</div>
                </li>
                {% endfor %}
            </ul>
            <ul v-show="f1_tab===2" class="goods_list fl">
                {% for content in contents.index_1f_cxdj %}
                <li>
                    <a href="{{ content.url }}" class="goods_pic"><img src="{{ content.image.url }}"></a>
                    <h4><a href="{{ content.url }}" title="{{ content.title }}">{{ content.title }}</a></h4>
                    <div class="prize">{{ content.text }}</div>
                </li>
                {% endfor %}
            </ul>
            <ul v-show="f1_tab===3" class="goods_list fl">
                {% for content in contents.index_1f_sjpj %}
                <li>
                    <a href="{{ content.url }}" class="goods_pic"><img src="{{ content.image.url }}"></a>
                    <h4><a href="{{ content.url }}" title="{{ content.title }}">{{ content.title }}</a></h4>
                    <div class="prize">{{ content.text }}</div>
                </li>
                {% endfor %}
            </ul>
        </div>
    </div>

    <div class="list_model model02">
            <div class="list_title clearfix">
                <h3 class="fl" id="model01">2F 电脑数码</h3>
                <div class="subtitle fr">
                    <a @mouseenter="f2_tab=1" :class="f2_tab===1?'active':''">加价换购</a>
                    <a @mouseenter="f2_tab=2" :class="f2_tab===2?'active':''">畅享低价</a>
                </div>
            </div>
            <div class="goods_con clearfix">
                <div class="goods_banner fl">
                    <img src="{{ contents.index_2f_logo.0.image.url}}">
                    <div class="channel">
                        {% for content in contents.index_2f_pd %}
                        <a href="{{ content.url }}">{{ content.title }}</a>
                        {% endfor %}
                    </div>
                    <div class="key_words">
                        {% for content in contents.index_2f_bq %}
                        <a href="{{ content.url }}">{{ content.title }}</a>
                        {% endfor %}
                    </div>
                </div>
                <ul v-show="f2_tab===1" class="goods_list fl">
                    {% for content in contents.index_2f_jjhg %}
                    <li>
                        <a href="{{ content.url }}" class="goods_pic"><img src="{{ content.image.url }}"></a>
                        <h4><a href="{{ content.url }}" title="{{ content.title }}">{{ content.title }}</a></h4>
                        <div class="prize">{{ content.text }}</div>
                    </li>
                    {% endfor %}
                </ul>
                <ul v-show="f2_tab===2" class="goods_list fl">
                    {% for content in contents.index_2f_cxdj %}
                    <li>
                        <a href="{{ content.url }}" class="goods_pic"><img src="{{ content.image.url }}"></a>
                        <h4><a href="{{ content.url }}" title="{{ content.title }}">{{ content.title }}</a></h4>
                        <div class="prize">{{ content.text }}</div>
                    </li>
                    {% endfor %}
                </ul>
            </div>
        </div>

        <div class="list_model model03">
            <div class="list_title clearfix">
                <h3 class="fl" id="model01">3F 家居家装</h3>
                <div class="subtitle fr">
                    <a @mouseenter="f3_tab=1" :class="f3_tab===1?'active':''">生活用品</a>
                    <a @mouseenter="f3_tab=2" :class="f3_tab===2?'active':''">厨房用品</a>
                </div>
            </div>
            <div class="goods_con clearfix">
                <div class="goods_banner fl">
                    <img src="{{ contents.index_3f_logo.0.image.url }}">
                    <div class="channel">
                        {% for content in contents.index_3f_pd %}
                        <a href="{{ content.url }}">{{ content.title }}</a>
                        {% endfor %}
                    </div>
                    <div class="key_words">
                        {% for content in contents.index_3f_bq %}
                        <a href="{{ content.url }}">{{ content.title }}</a>
                        {% endfor %}
                    </div>
                </div>
                <ul v-show="f3_tab===1" class="goods_list fl">
                    {% for content in contents.index_3f_shyp %}
                    <li>
                        <a href="{{ content.url }}" class="goods_pic"><img src="{{ content.image.url }}"></a>
                        <h4><a href="{{ content.url }}" title="{{ content.title }}">{{ content.title }}</a></h4>
                        <div class="prize">{{ content.text }}</div>
                    </li>
                    {% endfor %}
                </ul>
                <ul v-show="f3_tab===2" class="goods_list fl">
                    {% for content in contents.index_3f_cfyp %}
                    <li>
                        <a href="{{ content.url }}" class="goods_pic"><img src="{{ content.image.url }}"></a>
                        <h4><a href="{{ content.url }}" title="{{ content.title }}">{{ content.title }}</a></h4>
                        <div class="prize">{{ content.text }}</div>
                    </li>
                    {% endfor %}
                </ul>
            </div>
        </div>

    <div class="footer">
        <div class="foot_link">
            <a href="#">关于我们</a>
            <span>|</span>
            <a href="#">联系我们</a>
            <span>|</span>
            <a href="#">招聘人才</a>
            <span>|</span>
            <a href="#">友情链接</a>
        </div>
        <p>CopyRight © 2016 北京********股份有限公司 All Rights Reserved</p>
        <p>电话:010-****888    京ICP备*******8号</p>
    </div>
    </div>
    <script type="text/javascript" src="js/index.js"></script>
</body>
</html>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309

新建scripts目录(存储静态化首页的手动脚本)

regenerate_index_html.py

#!/usr/bin/env python

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

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

 # 让django进行初始化设置
import django
django.setup()

from contents.crons import generate_static_index_html


if __name__ == '__main__':
    generate_static_index_html()
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

为脚本添加可执行权限

chmod +x regenerate_index_html.py
  
  
  • 1

测试执行

这里写图片描述

下一步 定时任务

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

安装

pip install django-crontab
  
  
  • 1

在settings中添加任务

INSTALLED_APPS = [
    ...
    'django_crontab',  # 定时任务
    ...
]
  
  
  • 1
  • 2
  • 3
  • 4
  • 5

设置任务的定时时间
在配置文件中设置定时执行的时间
每个定时任务分为三部分定义:
任务时间

基本格式 :

* * * * *

分 时 日 月 周      命令

M: 分钟(0-59)。每分钟用*或者 */1表示

H:小时(0-23)。(0表示0点)

D:天(1-31)。

m: 月(1-12)。

d: 一星期内的天(0~6,0为星期天)。
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

添加任务到settings中

# 定时任务
CRONJOBS = [
    # 每5分钟执行一次生成主页静态文件
    ('*/5 * * * *', 'contents.crons.generate_static_index_html', '>> /home/python/Desktop/meiduo/mall/logs/crontab.log')
]
  
  
  • 1
  • 2
  • 3
  • 4
  • 5

遇到问题

在定时任务中,如果出现非英文字符,会出现字符异常错误
可以通过在配置文件中添加定时任务执行的附加命令来实现

# 解决crontab中文问题
CRONTAB_COMMAND_PREFIX = 'LANG_ALL=zh_cn.UTF-8'
  
  
  • 1
  • 2

开启定时任务
添加定时任务到系统中

python manage.py crontab add
  
  
  • 1

显示已经激活的定时任务

python manage.py crontab show
  
  
  • 1

移除定时任务

python manage.py crontab remove
  
  
  • 1

到此为止,我们就完成一个页面的静态化流程,希望朋友们点个赞呗!

猜你喜欢

转载自blog.csdn.net/myword1314/article/details/82867018
今日推荐