用 Flask 来写个轻博客 (27) — 使用 Flask-Cache 实现网页缓存加速
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog
目录
- 目录
- 前文列表
- 扩展阅读
- Flask-Cache
- 应用 Flask-Cache 实现视图函数缓存
- 缓存无参数的普通函数
- 缓存带参数的普通函数
- 缓存无动态参数的视图函数
- 缓存带动态参数的视图函数
前文列表
用 Flask 来写个轻博客 (1) — 创建项目
用 Flask 来写个轻博客 (2) — Hello World!
用 Flask 来写个轻博客 (3) — (M)VC_连接 MySQL 和 SQLAlchemy
用 Flask 来写个轻博客 (4) — (M)VC_创建数据模型和表
用 Flask 来写个轻博客 (5) — (M)VC_SQLAlchemy 的 CRUD 详解
用 Flask 来写个轻博客 (6) — (M)VC_models 的关系(one to many)
用 Flask 来写个轻博客 (7) — (M)VC_models 的关系(many to many)
用 Flask 来写个轻博客 (8) — (M)VC_Alembic 管理数据库结构的升级和降级
用 Flask 来写个轻博客 (9) — M(V)C_Jinja 语法基础快速概览
用 Flask 来写个轻博客 (10) — M(V)C_Jinja 常用过滤器与 Flask 特殊变量及方法
用 Flask 来写个轻博客 (11) — M(V)C_创建视图函数
用 Flask 来写个轻博客 (12) — M(V)C_编写和继承 Jinja 模板
用 Flask 来写个轻博客 (13) — M(V)C_WTForms 服务端表单检验
用 Flask 来写个轻博客 (14) — M(V)C_实现项目首页的模板
用 Flask 来写个轻博客 (15) — M(V)C_实现博文页面评论表单
用 Flask 来写个轻博客 (16) — MV(C)_Flask Blueprint 蓝图
用 Flask 来写个轻博客 (17) — MV(C)_应用蓝图来重构项目
用 Flask 来写个轻博客 (18) — 使用工厂模式来生成应用对象
用 Flask 来写个轻博客 (19) — 以 Bcrypt 密文存储账户信息与实现用户登陆表单
用 Flask 来写个轻博客 (20) — 实现注册表单与应用 reCAPTCHA 来实现验证码
用 Flask 来写个轻博客 (21) — 结合 reCAPTCHA 验证码实现用户注册与登录
用 Flask 来写个轻博客 (22) — 实现博客文章的添加和编辑页面
用 Flask 来写个轻博客 (23) — 应用 OAuth 来实现 Facebook 第三方登录
用 Flask 来写个轻博客 (24) — 使用 Flask-Login 来保护应用安全
用 Flask 来写个轻博客 (25) — 使用 Flask-Principal 实现角色权限功能
用 Flask 来写个轻博客 (26) — 使用 Flask-Celery-Helper 实现异步任务
扩展阅读
Flask-Cache — Flask-Cache 0.13 documentation
缓存— Flask 0.10.1 documentation
Flask-Cache
网页的加载时间决定了你的网站是否能够受到用户的欢迎, 现在为止我们 blog 应用模板的每次渲染都会查询数据库, 这是不合理的. 对一些数据不被经常改变的页面我们应该引入缓存的机制来减少对数据库的访问.
Flask-Cache 能够让我们把视图函数返回的结果缓存下来, 以后再次渲染时, 只需要从缓存中取出这些结果就可以了, 无须重复的渲染.
- 安装
pip install Flask-Cache
pip freeze > requirement.txt
应用 Flask-Cache 实现视图函数缓存
- 初始化
vim jmilkfansblog/extensions.py
from flask.ext.cache import Cache...#### Create the Flask-Cache's instance
cache = Cache()
- 将 cache 对象注册到 app 对象中
vim jmilkfansblog/__init__.py
from jmilkfansblog.extensions import cache...def create_app(object_name):"""Create the app instance via `Factory Method`"""
...#### Init the Flask-Cache via app objectcache.init_app(app)
- 配置 Cache 类型
class DevConfig(Config):"""Development config class."""
...#### Flask-Cache's configCACHE_TYPE = 'simple'
Flask-Cache 定义缓存的方式就是为你需要缓存的函数加上缓存装饰器, 这样的装饰器由多种类型, 对应装饰在不同的函数或视图函数中.
缓存无参数的普通函数
vim jmilkfansblog/controllers/blog.py
@cache.cached(timeout=7200, key_prefix='sidebar_data')
def sidebar_data():"""Set the sidebar function."""# Get post of recentrecent = db.session.query(Post).order_by(Post.publish_date.desc()).limit(5).all()# Get the tags and sort by count of posts.top_tags = db.session.query(Tag, func.count(posts_tags.c.post_id).label('total')).join(posts_tags).group_by(Tag).order_by('total DESC').limit(5).all()return recent, top_tags
NOTE 1: 装饰器 @ cache.cached()
的形参数 key_prefix 是必须的, 并且传入的值是唯一的, 这样 Flask-Cache 才能够正确的返回该函数缓存的值.
NOTE 2: 该函数被缓存的时间设定为 2 小时, 这是因为该函数返回的值不被经常改变, 而且就算是被改变了也不会对整体页面的显示有大的影响.
缓存带参数的普通函数
装饰器 cache.cached()
不会考虑到参数的问题, 如果函数在接收到不同的实参后还返回相同结果的话, 这明显是不科学的. 为了解决这个问题, 我们使用 @cache.memoize()
装饰器来定义.
vim jmilkfansblog/models.py
@staticmethod@cache.memoize(60)def verify_auth_token(token):"""Validate the token whether is night."""serializer = Serializer(current_app.config['SECRET_KEY'])try:# serializer object already has tokens in itself and wait for # compare with token from HTTP Request /api/posts Method `POST`.data = serializer.loads(token)except SignatureExpired:return Noneexcept BadSignature:return Noneuser = User.query.filter_by(id=data['id']).first()return user
NOTE 1: 装饰器 @cache.memoize()
不仅仅会缓存运行的结果, 还缓存调用时的参数, 所以在函数接受到相同的参数时, 就会将缓存中该参数对应的结果返回.
NOTE 2: @cache.momoize()
非常不适用于返回结果依赖全局变量或依赖数据库查询的函数, 因为在这很容易导致数据竞态, 即输入了相同的参数, 可能会返回不同的结果. 最适合被缓存的函数是纯函数(在传入的参数相同的情况下会输出相同的结果)
缓存无动态参数的视图函数
# Use the Blueprint object to set the Route URL
# Register the view function into blueprint
@blog_blueprint.route('/')
@blog_blueprint.route('/<int:page>')
@cache.cached(timeout=60)
def home(page=1):"""View function for home page"""posts = Post.query.order_by(Post.publish_date.desc()).paginate(page, 10)recent, top_tags = sidebar_data()return render_template('home.html',posts=posts,recent=recent,top_tags=top_tags)
NOTE 1: 这里仍然是使用装饰器 @cache.cached()
, 但却不必需要指定 key_prefix 形参.
NOTE 2: timeout 表示该视图函数返回的结果将会被缓存的时长.
缓存带动态参数的视图函数
因为该类型视图函数的参数 post_id 是被动态解析成为 URL(/post/<string:post_id>
) 的, 所以并不是每一次调用都会返回相同的结果, 这样就需要我们进一步的确认, 只有在确定两次不同请求的都是同一个目标(即 URL)时, 才会将缓存返回, 否则创建一个新的缓存.
def make_cache_key(*args, **kwargs):"""Dynamic creation the request url."""path = request.pathargs = str(hash(frozenset(request.args.items())))return (path + args).encode('utf-8')
...@blog_blueprint.route('/post/<string:post_id>', methods=('GET', 'POST'))
@cache.cached(timeout=60, key_prefix=make_cache_key)
def post(post_id):"""View function for post page"""# Form object: `Comment`form = CommentForm()...
NOTE 1: 这里我们仍然使用了 key_prefix 参数来进行定位, 而且该形参除了可以接受 String 类型对象之后, 也可以接收一个函数.
NOTE 2: 函数 make_cache_key()
会动态的生成一个唯一的缓存键, 用于确定这一次请求的 URL 是否存在缓存, 如果存在则返回, 如果不存在则新建. 所以在该函数中我们使用了请求 path + hash 字符串结合而成的唯一字符串作为缓存键.
用 Flask 来写个轻博客 (27) — 使用 Flask-Cache 实现网页缓存加速相关推荐
- 用 Flask 来写个轻博客 (37) — 在 Github 上为第一阶段的版本打 Tag
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 第一阶段结语 打 Tag 前文列表 用 Flask 来写个轻博客 (1 ...
- 用 Flask 来写个轻博客 (36) — 使用 Flask-RESTful 来构建 RESTful API 之五
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 PUT 请求 DELETE 请求 测试 对一条已经存在的 posts ...
- 用 Flask 来写个轻博客 (35) — 使用 Flask-RESTful 来构建 RESTful API 之四
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 POST 请求 身份认证 测试 前文列表 用 Flask 来写个轻博客 ...
- 用 Flask 来写个轻博客 (34) — 使用 Flask-RESTful 来构建 RESTful API 之三
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 应用请求中的参数实现 API 分页 测试 前文列表 用 Flask 来 ...
- 用 Flask 来写个轻博客 (33) — 使用 Flask-RESTful 来构建 RESTful API 之二
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 构建 RESTful Flask API 定义资源路由 格式 ...
- 用 Flask 来写个轻博客 (32) — 使用 Flask-RESTful 来构建 RESTful API 之一
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 RESTful API REST 原则 无状态原则 面向资源 ...
- 用 Flask 来写个轻博客 (31) — 使用 Flask-Admin 实现 FileSystem 管理
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 编写 FileSystem Admin 页面 Flask-A ...
- 用 Flask 来写个轻博客 (30) — 使用 Flask-Admin 增强文章管理功能
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 实现文章管理功能 实现效果 前文列表 用 Flask 来写个 ...
- 用 Flask 来写个轻博客 (29) — 使用 Flask-Admin 实现后台管理 SQLAlchemy
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 Flask-Admin BaseView 基础管理页面 Mo ...
最新文章
- Rhythmk 一步一步学 JAVA(11)Ibatis 环境配置
- 人工智能离我们有多远/近?
- 利用 CSS selector 改变悬停表格样式
- 软件概要设计和详细设计的区别
- 变量之--列表初始化和结构化绑定
- 程序开机全屏且不能见任何windows界面、不能使用系统热键
- 关于工程技术中PE、ME、TE、IE、EE的解说
- squid服务配置(正向、反向代理)
- mysql 5.6.17 x64 安装
- 一文初探Tensorflow高级API使用(初学者篇)
- CSS的预编译——less语言基本语法教程(入门)
- 框架中的Blob数据的定义
- C语言32个关键字详解
- html买手机的流程图,支付流程图.html
- 最优化学习 拟牛顿法(Quasi-Newton Method)
- 教你win10浏览器禁用加载项操作方法【系统天地】
- 【微信小程序原生】 上传图片和视频
- 如何快速的删除空间黑历史说说
- C++后端开发知识点总结
- 《Cortex-CM3权威指南》——存储器系统
热门文章
- java强制转换成float_在Java中什么时候double必须强制转换成float 就是要在数值后加f或者强制转换...
- 佳能7010c打印黑竖条_公司上市,老板发财,员工开心的秘密,竟然都在这台小小的打印机里?...
- centos sudo不能运行_如何在 Linux 中配置 sudo 访问权限 | Linux 中国
- Unigui 服务器解析php,如何正确使用uniGUI的HyperServer(负载均衡)功能
- python爬取淘宝商品做数据挖掘_Python 3爬虫 数据清洗与可视化实战 Python数据抓取技术 python3网络爬虫教程书籍 运用Python工具获取电商平台页面数据挖掘书籍...
- 看完书要及时消化(1)《暗时间》
- 分分钟get「隔空传手」技能,网友:我想试试别的东西…
- 今年你的双11包裹,也是自动驾驶卡车送来的吗?
- 2位华人获得加州理工学院计算机、数学博士奖学金,3年近一半由华人获得
- 全球奖金最高的科学奖项颁发:黑洞拍摄团队、肥胖症治疗等获奖;2位清华北大校友入围...