如何优雅地改进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内置的字符串处理函数整理
Jan 29 Python
linux系统使用python监测系统负载脚本分享
Jan 15 Python
Python的Flask框架及Nginx实现静态文件访问限制功能
Jun 27 Python
关于Python中浮点数精度处理的技巧总结
Aug 10 Python
Python基础之getpass模块详细介绍
Aug 10 Python
python爬虫 使用真实浏览器打开网页的两种方法总结
Apr 21 Python
Python使用Selenium模块实现模拟浏览器抓取淘宝商品美食信息功能示例
Jul 18 Python
在Python中pandas.DataFrame重置索引名称的实例
Nov 06 Python
Python常见的pandas用法demo示例
Mar 16 Python
Python后台开发Django的教程详解(启动)
Apr 08 Python
python with语句的原理与用法详解
Mar 30 Python
Python ckeditor富文本编辑器代码实例解析
Jun 22 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
ThinkPHP中where()使用方法详解
2016/04/19 PHP
Yii2使用自带的UploadedFile实现的文件上传
2016/06/20 PHP
php获取目录下所有文件及目录(多种方法)(推荐)
2019/05/14 PHP
PHP Trait代码复用类与多继承实现方法详解
2019/06/17 PHP
拖动Html元素集合 Drag and Drop any item
2006/12/22 Javascript
JQuery 操作Javascript对象和数组的工具函数小结
2010/01/22 Javascript
JQuery中getJSON的使用方法
2010/12/13 Javascript
jQuery之尺寸调整组件的深入解析
2013/06/19 Javascript
Jquery下EasyUI组件中的DataGrid结果集清空方法
2014/01/06 Javascript
简介JavaScript中的push()方法的使用
2015/06/09 Javascript
把json格式的字符串转换成javascript对象或数组的方法总结
2016/11/03 Javascript
Mongoose学习全面理解(推荐)
2017/01/21 Javascript
基于JavaScript实现瀑布流效果
2017/03/29 Javascript
详解用vue.js和laravel实现微信授权登陆
2017/06/23 Javascript
vue项目关闭eslint校验
2018/03/21 Javascript
小程序视频或音频自定义可拖拽进度条的示例代码
2018/09/30 Javascript
详解Node.js使用token进行认证的简单示例
2020/05/25 Javascript
swiper自定义分页器的样式
2020/09/14 Javascript
python修改操作系统时间的方法
2015/05/18 Python
python的dataframe转换为多维矩阵的方法
2018/04/11 Python
Python+selenium实现自动循环扔QQ邮箱漂流瓶
2018/05/29 Python
python爬虫简单的添加代理进行访问的实现代码
2019/04/04 Python
python反转列表的三种方式解析
2019/11/08 Python
Django通过dwebsocket实现websocket的例子
2019/11/15 Python
Django Admin后台添加数据库视图过程解析
2020/04/01 Python
python 实现图像快速替换某种颜色
2020/06/04 Python
python名片管理系统开发
2020/06/18 Python
html5需遵循的6个设计原则
2016/04/27 HTML / CSS
html5自定义video标签的海报与播放按钮功能
2019/12/04 HTML / CSS
《乡愁》教学反思
2014/02/18 职场文书
财务部总监岗位职责
2014/03/12 职场文书
机关作风建设剖析材料
2014/10/11 职场文书
加薪申请报告范本
2015/05/15 职场文书
试了下Golang实现try catch的方法
2021/07/01 Golang
Python实现文字pdf转换图片pdf效果
2022/04/03 Python
Redis主从复制操作和配置详情
2022/09/23 Redis