国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

如何優雅地改進Django中的模板碎片緩存詳解

2020-02-15 22:12:33
字體:
來源:轉載
供稿:網友

前言

本文主頁給大家介紹了關于如何改進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 cachedef 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, # 回調函數 )            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 集贤县| 行唐县| 依兰县| 宁晋县| 凤庆县| 寿宁县| 绥阳县| 景泰县| 斗六市| 涟水县| 阜康市| 吐鲁番市| 巩留县| 武宣县| 日照市| 文化| 宜宾县| 崇文区| 两当县| 仙游县| 十堰市| 萝北县| 拉萨市| 岳阳市| 大竹县| 湄潭县| 厦门市| 南木林县| 含山县| 海门市| 上高县| 马边| 崇阳县| 奎屯市| 乌兰县| 武威市| 突泉县| 恩施市| 新宁县| 资中县| 旅游|