如何优雅地改进Django中的模板碎片缓存详解


Posted in Python onJuly 04, 2018

前言

本文主页给大家介绍了关于如何改进Django中模板碎片缓存的相关内容,关于Django模板碎片缓存大家可以先看看这篇文章,下面话不多说了,来一起看看详细的介绍吧

起步

Django 的缓存体系提供了模板片段缓存:

{% load cache %}
{% cache 500 sidebar %}
 .. sidebar ..
{% endcache %}

但使用这个模板缓存还是需要每次都把需要的变量 sidebar 传给模板,不然当缓存过期时碎片是空白的。于是就需要的视图中获取这些数据:

def test_view(request):
 # code...
 sidebar = get_data()
 return render(reqeust, 'test_view.html', {'sidebar': sidebar})

如果这个数据获取的过程比较耗时,那么这个碎片缓存形同虚设。

低级缓存

使用低级缓存能解决数据获取耗时问题:

from django.core.cache import cache
def get_data():
 key = 'hot-course'
 result = cache.get(key)
 if result:
 return result
 # 比较耗时的数据获取
 result = Course.objects.filter().order_by('-fav_num')[:10]
 cache.set(key, result, 600) # 保存至缓存
 return result

这样一般就能解决数据来源耗时问题,一般用了这个方式就不会再用模板碎片缓存了,不然内存中就有两个缓存了,一个是原始数据,另一个是渲染成 html 代码的结果。有点多余,内存宝贵应该用于刀刃上,而且两个缓存的方式极不优雅。

使用这种底层 api 后,还是需要把数据传递到视图层,如果是公共部分的如轮播部分的视图,是会被其他模板 include 的,那就需要其他视图函数也都获取一次数据,再传递到模板层。重复的代码会很多。

有没有一种好的办法解决这种情况呢?

优雅的改进碎片缓存

改进的碎片缓存需要能按需获取,最好不需要视图层的参与。这个要求可以通过标签来实现,我们来自己实现一下这个缓存标签,在此之前呢,需要做个通用的缓存工具,能够传入数据获取的函数来做回调,这部分其实和 Django 的 django.templatetags.CacheNode 类基本一样。我这边就写与其不一样的地方:

class UserCacheNode(Node):
 """
 优雅的自定义模板碎片缓存
 """
 def __init__(self, nodelist, expire_time_var, fragment_name, vary_on, cache_name, fun=None):
 # ...
 self.fun = fun # 用于数据获取的回调函数

 def render(self, context:dict):
 # ...
 if value is None:
  if self.fun: # 实行回调
  context.update(self.fun(*vary_on))
  value = self.nodelist.render(context)
  fragment_cache.set(cache_key, value, expire_time) # 保存至缓存
 return value

然后是制作自定义标签:

def get_hot_course():
 # 做会调用,函数返回字典
 print("call hot course")
 hot_courses = Course.objects.filter().order_by('stu_nums')[:5]
 return locals()

@register.tag('hot_course_cache') # 自定义的标签名称
def hot_course_cache(parser, token):
 nodelist = parser.parse(('endcache',))
 parser.delete_first_token()
 tokens = token.split_contents()
 cache_name = None

 return UserCacheNode(
 nodelist, parser.compile_filter(tokens[1]),
 tokens[2], # fragment_name can't be a variable.
 [parser.compile_filter(t) for t in tokens[3:]],
 cache_name,
 fun=get_hot_course, # 回调函数
 )

然后在模板中就可以这么使用:

{% load course_tag %}
{% hot_course_cache 500 hot_courses %}
 ...hot_courses...
{% endcache %}

通过用自定义标签的方式,就无需视图层的参与了,缓存标签的使用方式也和体系中的 cache 相似,由于是自定义的标签,一些 IDE 会有一些警告,比如我的开发环境:

如何优雅地改进Django中的模板碎片缓存详解

运行上是没问题的,IDE 可能对这类自定义标签的支持度不是很好吧。

参考

Django's cache framework

Custom template tags and filters

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python中用Descriptor实现类级属性(Property)详解
Sep 18 Python
Python排序算法实例代码
Aug 10 Python
python创建列表和向列表添加元素的实现方法
Dec 25 Python
详解python 爬取12306验证码
May 10 Python
python基于Selenium的web自动化框架
Jul 14 Python
淘宝秒杀python脚本 扫码登录版
Sep 19 Python
Python和Anaconda和Pycharm安装教程图文详解
Feb 04 Python
python数据分析工具之 matplotlib详解
Apr 09 Python
基于SQLAlchemy实现操作MySQL并执行原生sql语句
Jun 10 Python
PyQt5的相对布局管理的实现
Aug 07 Python
超级实用的8个Python列表技巧
Aug 24 Python
windows系统Tensorflow2.x简单安装记录(图文)
Jan 18 Python
Django框架多表查询实例分析
Jul 04 #Python
python 借助numpy保存数据为csv格式的实现方法
Jul 04 #Python
Python将一个CSV文件里的数据追加到另一个CSV文件的方法
Jul 04 #Python
python中csv文件的若干读写方法小结
Jul 04 #Python
Python画柱状统计图操作示例【基于matplotlib库】
Jul 04 #Python
pandas将numpy数组写入到csv的实例
Jul 04 #Python
Python实现的简单排列组合算法示例
Jul 04 #Python
You might like
汉字转化为拼音(php版)
2006/10/09 PHP
php urlencode()与urldecode()函数字符编码原理详解
2011/12/06 PHP
php中判断文件存在是用file_exists还是is_file的整理
2012/09/12 PHP
php编写的简单页面跳转功能实现代码
2013/11/27 PHP
php获取、检查类名、函数名、方法名的函数方法
2015/06/25 PHP
jquery实现excel导出的方法
2013/04/04 Javascript
onbeforeunload与onunload事件异同点总结
2013/06/24 Javascript
node.js中格式化数字增加千位符的几种方法
2015/07/03 Javascript
js判断一个字符串是以某个字符串开头的简单实例
2016/12/27 Javascript
js实现文字跑马灯效果
2017/02/23 Javascript
详解vue.js 开发环境搭建最简单攻略
2017/06/12 Javascript
VUE axios发送跨域请求需要注意的问题
2017/07/06 Javascript
深入理解jquery的$.extend()、$.fn和$.fn.extend()
2017/07/08 jQuery
详解vue-cli 构建项目 vue-cli请求后台接口 vue-cli使用axios、sass、swiper
2018/05/28 Javascript
通过cordova将vue项目打包为webapp的方法
2019/02/02 Javascript
Node.js之readline模块的使用详解
2019/03/25 Javascript
vue使用video.js进行视频播放功能
2019/07/18 Javascript
js实现开关灯效果
2020/03/30 Javascript
vue实现路由懒加载的3种方法示例
2020/09/01 Javascript
vue 递归组件的简单使用示例
2021/01/14 Vue.js
Python实现多线程抓取妹子图
2015/08/08 Python
python机器学习理论与实战(二)决策树
2018/01/19 Python
Python元组拆包和具名元组解析实例详解
2018/03/26 Python
pandas 实现将重复表格去重,并重新转换为表格的方法
2018/04/18 Python
Python3 tkinter 实现文件读取及保存功能
2019/09/12 Python
python+tifffile之tiff文件读写方式
2020/01/13 Python
毕业生自荐信
2013/12/14 职场文书
大学毕业生个人自荐信范文
2014/01/08 职场文书
优秀毕业生自荐信
2014/06/10 职场文书
2014年个人技术工作总结
2014/12/08 职场文书
青年文明号汇报材料
2014/12/23 职场文书
推荐信范文大全
2015/03/27 职场文书
2019年大学推荐信
2019/06/24 职场文书
标准版个人借条怎么写?以及什么是借条?
2019/08/28 职场文书
Javascript 解构赋值详情
2021/11/17 Javascript
Python可视化神器pyecharts绘制水球图
2022/07/07 Python