首先为什么我们要将页面静态化呢?
首先我们来讲讲页面静态化的优点
:
- 1:加快网站的运行速度,提升客户体验
- 2:减少对后端服务器的压力
其次我们再来讲讲页面静态化处理的一些要求
?
- 跟客户信息相关的内容,不要包含在静态化内容里面
- 经常变化的内容,最好不要包含在静态内容里面
- 更新频率过高的内容,不适合静态化
最后我们讲讲为何选择首页
来进行页面静态化处理?
- 第一,由于首页展示信息变化频率比较低
- 第二,首页是每个登录用户必须访问的页面,因此访问率很高
- 第三,首页信息牵扯到较多数据库查询,在高并发的访问情况下,对服务器压力很大。
- 第四,可以防止DDOS攻击
说明:DdoS的攻击方式有很多种,最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应,分布式的拒绝服务攻击手段DDoS就是利用更多的傀儡机(肉鸡)来发起进攻,以比从前更大的规模来进攻受害者。
页面静态化实现思路
基本的思路大都是:根据模板,从后端服务器和数据库动态获取数据,然后组合起来,形成静态页面的内容,再将静态页面保存起来,利用nginx做代理。
页面静态化实战
我们采用celery分布式任务模块来生成静态页面
在进行首页页面静态化处理之前我们需要先思考一下:在什么时候我们需要对更新静态页面
- 第一,首页页面新增数据
- 第二,首页页面删除数据
- 第三,首页页面修改数据
步骤
(1)通过celery
生成静态页面
- 在
tasks.py
任务模块(关于celery
在之前文章中已经写的很详细,请自行查阅)中新建任务函数,进行数据库查询,查找出首页需要展示的内容之后,将数据与模板进行渲染,然后将渲染好的模板保存在static
静态目录中。
from celery import Celery
from django.template import loader
import os
from goods.models import GoodsType, IndexGoodsBanner, IndexPromotionBanner, IndexTypeGoodsBanner
app = Celery('celery_tasks.tasks', broker='redis://192.168.153.132/2')
@app.task
def generate_static_index_html():
"""产生静态页面"""
# 获取商品的种类信息
types = GoodsType.objects.all()
# 获取首页轮播商品信息
goods_banners = IndexGoodsBanner.objects.all().order_by('index')
# 获取首页促销活动信息
promotion_banners = IndexPromotionBanner.objects.all().order_by('index')
# 获取首页分类商品展示信息
for type in types:
# 获取type种类首页分类商品的图片展示信息
image_banners = IndexTypeGoodsBanner.objects.filter(type=type, display_type=1).order_by('index')
# 获取type种类首页分类商品的文字展示信息
title_banners = IndexTypeGoodsBanner.objects.filter(type=type, display_type=0).order_by('index')
# 动态给type增加属性,分别保存首页分类商品的图片展示信息和文字展示信息
type.image_banners = image_banners
type.title_banners = title_banners
# 组织模板上下文
context = {
"types": types,
"goods_banners": goods_banners,
"promotion_banners": promotion_banners,
}
# 1.加载模板文件,返回模板对象
temp = loader.get_template('static_index.html')
# 2.模板渲染
static_index_html = temp.render(context)
# 生成首页对应的静态文件
save_path = os.path.join(settings.BASE_DIR, 'static/index.html')
with open(save_path, 'w') as f:
f.write(static_index_html)
(2)通过nginx
向用户提供该静态页面
# 修改nginx配置文件
cd /usr/local/nginx/conf/
vim nginx.conf
server {
listen 80;
server_name localhost;
location /static {
# 项目静态文件存储路径
alias /home/fatpuffer/myproject/dailyfresh/static;
}
location / {
# 项目静态文件存储路径
root /home/fatpuffer/myproject/dailyfresh/static;
# 默认访问文件
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
(3)管理员修改后台数据时重新生成静态页面,那么我们怎么知道管理员什么时候修改数据?
Django Admin
站点中每一个后台管理页面都可以定义一个模型管理类,继承自admin.ModelAdmin
.ModelAdmin
中的两个方法:save_model
(管理员添加或更新表里数据时会自动调用),delete_model
(管理员删除表中数据时会自动调用)- 所以我们只需要在这两个方法内发送我们定义好的
celery
任务,在用户修改数据库数据时就会重新生成首页静态页面 - 我们首页展示路由配置放在了
goods
商品应用模块中,所以我们需要打开goods/admin.py
文件(每个人根据自己项目实际情况处理) - 我们要实现首页页面的静态化,所以只需要对首页页面用到的模型类进行处理即可
from django.contrib import admin
from django.core.cache import cache
from goods.models import GoodsType # 商品类型类
from goods.models import IndexGoodsBanner # 首页轮播商品展示模型类
from goods.models import IndexPromotionBanner # 首页促销活动模型类
from goods.models import IndexTypeGoodsBanner # 首页分类商品展示模型类
class BaseModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
"""新增或更新表中的数据时调用"""
super().save_model(request, obj, form, change)
# celery_task:是我存放celery_task任务文件tasks.py的目录,与项目其他应用评级
from celery_task.tasks import generate_static_index_html
# 调用celery任务重新生成静态页面
generate_static_index_html.delay()
# 清除首页的缓存数据
cache.delete('index_page_data')
def delete_model(self, request, obj):
"""删除表中的数据时调用"""
super().delete_model(request, obj)
# celery_task:是我存放celery_task任务文件tasks.py的目录,与项目其他应用评级
from celery_task.tasks import generate_static_index_html
# 调用celery任务重新生成静态页面
generate_static_index_html.delay()
# 清除首页的缓存数据
cache.delete('index_page_data')
# 由于admin.ModelAdmin中的两个方法相同,所以我们定义一个基类,使以下四个类都继承此类
class GoodsTypeAdmin(BaseModelAdmin):
pass
class IndexGoodsBannerAdmin(BaseModelAdmin):
pass
class IndexTypeGoodsBnanerAdmin(BaseModelAdmin):
pass
class IndexPormotionBannerAdmin(BaseModelAdmin):
pass
# 注册模型类到后台管理
# 管理员修改GoodsType模型类里面的数据,将会调用GoodsTypeAdmin这个类里面的方法
admin.site.register(GoodsType, GoodsTypeAdmin)
admin.site.register(IndexGoodsBanner, IndexGoodsBannerAdmin)
admin.site.register(IndexPromotionBanner, IndexPormotionBannerAdmin)
admin.site.register(IndexTypeGoodsBanner, IndexTypeGoodsBnanerAdmin)
(4)一切准备就绪,那么我们应该在何时给用户返回celery生成的静态页面,何时返回我们视图请求生成的页面。
- 一般在我们网站搭建好后,会在用户访问我们服务器之前做一个
nginx
反响代理,不会暴露我们服务器的真实ip,同时还可以通过这个代理服务器实现负载均衡,以及数据的缓存,可以提高我们网站的性能,更好的应对高并发。 - 在我们使用nginx时可以通过配置来实现上述问题。
当用户访问地址是:127.0.0.1:8000/index
我们返回视图处理函数数据
当用户访问的是:127.0.0.1
我们返回生成的静态页面