如何优雅地改进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去除列表中重复元素的方法
Mar 20 Python
浅谈Python单向链表的实现
Dec 24 Python
python 实现自动远程登陆scp文件实例代码
Mar 13 Python
python之验证码生成(gvcode与captcha)
Jan 02 Python
python3实现指定目录下文件sha256及文件大小统计
Feb 25 Python
一篇文章弄懂Python中所有数组数据类型
Jun 23 Python
python实现的分析并统计nginx日志数据功能示例
Dec 21 Python
Django mysqlclient安装和使用详解
Sep 17 Python
python爬虫用scrapy获取影片的实例分析
Nov 23 Python
Python 实现劳拉游戏的实例代码(四连环、重力四子棋)
Mar 03 Python
Python装饰器详细介绍
Mar 25 Python
请求模块urllib之PYTHON爬虫的基本使用
Apr 08 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数组和explode函数示例总结
2015/05/08 PHP
php图片上传类 附调用方法
2016/05/15 PHP
基于jquery的时间段实现代码
2012/08/02 Javascript
JS操作Cookies包括(读取添加与删除)
2012/12/26 Javascript
博客侧边栏模块跟随滚动条滑动固定效果的实现方法(js+jquery等)
2013/03/24 Javascript
使用Math.floor与Math.random取随机整数的方法详解
2013/05/07 Javascript
推荐5 个常用的JavaScript调试技巧
2015/01/08 Javascript
jQuery实现带动画效果的二级下拉导航方法
2015/03/11 Javascript
微信内置浏览器私有接口WeixinJSBridge介绍
2015/05/25 Javascript
使用postMesssage()实现跨域iframe页面间的信息传递方法
2016/03/29 Javascript
Google Maps基础及实例解析
2016/08/06 Javascript
微信小程序 增、删、改、查操作实例详解
2017/01/13 Javascript
使用vue.js2.0 + ElementUI开发后台管理系统详细教程(二)
2017/01/21 Javascript
微信小程序动态添加分享数据
2017/06/14 Javascript
聊聊JS动画库 Velocity.js的使用
2018/03/13 Javascript
vue中promise的使用及异步请求数据的方法
2018/11/08 Javascript
jQuery内容过滤选择器与子元素过滤选择器用法实例分析
2019/02/20 jQuery
微信小程序全局变量改变监听的实现方法
2019/07/15 Javascript
jquery实现简单每周轮换的日历
2020/09/10 jQuery
[02:00]DOTA2英雄COSPLAY闹市街头巡游助威2015国际邀请赛
2015/08/02 DOTA
Python操作MongoDB数据库PyMongo库使用方法
2015/04/27 Python
python获取多线程及子线程的返回值
2017/11/15 Python
Java分治归并排序算法实例详解
2017/12/12 Python
django初始化数据库的实例
2018/05/27 Python
python opencv人脸检测提取及保存方法
2018/08/03 Python
Python对ElasticSearch获取数据及操作
2019/04/24 Python
Python数据库小程序源代码
2019/09/15 Python
小白教你PyCharm从下载到安装再到科学使用PyCharm2020最新激活码
2020/09/25 Python
使用CSS3实现SVG路径描边动画效果入门教程
2019/10/21 HTML / CSS
HTML5中input[type='date']自定义样式与日历校验功能的实现代码
2017/07/11 HTML / CSS
捷克时尚网上商店:OTTO
2018/03/15 全球购物
意大利火车票和铁路通行证专家:ItaliaRail
2019/01/22 全球购物
荷兰天然和有机产品网上商城:BigGreenSmile.nl
2020/07/26 全球购物
一些网络技术方面的面试题
2014/05/01 面试题
《蒲公英》教学反思
2014/02/28 职场文书
2015年医院工作总结范文
2015/04/09 职场文书