如何優(yōu)雅地改進(jìn)Django中的模板碎片緩存詳解
前言
本文主頁(yè)給大家介紹了關(guān)于如何改進(jìn)Django中模板碎片緩存的相關(guān)內(nèi)容,關(guān)于Django模板碎片緩存大家可以先看看這篇文章,下面話(huà)不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧
起步
Django 的緩存體系提供了模板片段緩存:
{% load cache %} {% cache 500 sidebar %} .. sidebar .. {% endcache %}
但使用這個(gè)模板緩存還是需要每次都把需要的變量 sidebar 傳給模板,不然當(dāng)緩存過(guò)期時(shí)碎片是空白的。于是就需要的視圖中獲取這些數(shù)據(jù):
def test_view(request): # code... sidebar = get_data() return render(reqeust, 'test_view.html', {'sidebar': sidebar})
如果這個(gè)數(shù)據(jù)獲取的過(guò)程比較耗時(shí),那么這個(gè)碎片緩存形同虛設(shè)。
低級(jí)緩存
使用低級(jí)緩存能解決數(shù)據(jù)獲取耗時(shí)問(wèn)題:
from django.core.cache import cache def get_data(): key = 'hot-course' result = cache.get(key) if result: return result # 比較耗時(shí)的數(shù)據(jù)獲取 result = Course.objects.filter().order_by('-fav_num')[:10] cache.set(key, result, 600) # 保存至緩存 return result
這樣一般就能解決數(shù)據(jù)來(lái)源耗時(shí)問(wèn)題,一般用了這個(gè)方式就不會(huì)再用模板碎片緩存了,不然內(nèi)存中就有兩個(gè)緩存了,一個(gè)是原始數(shù)據(jù),另一個(gè)是渲染成 html 代碼的結(jié)果。有點(diǎn)多余,內(nèi)存寶貴應(yīng)該用于刀刃上,而且兩個(gè)緩存的方式極不優(yōu)雅。
使用這種底層 api 后,還是需要把數(shù)據(jù)傳遞到視圖層,如果是公共部分的如輪播部分的視圖,是會(huì)被其他模板 include 的,那就需要其他視圖函數(shù)也都獲取一次數(shù)據(jù),再傳遞到模板層。重復(fù)的代碼會(huì)很多。
有沒(méi)有一種好的辦法解決這種情況呢?
優(yōu)雅的改進(jìn)碎片緩存
改進(jìn)的碎片緩存需要能按需獲取,最好不需要視圖層的參與。這個(gè)要求可以通過(guò)標(biāo)簽來(lái)實(shí)現(xiàn),我們來(lái)自己實(shí)現(xiàn)一下這個(gè)緩存標(biāo)簽,在此之前呢,需要做個(gè)通用的緩存工具,能夠傳入數(shù)據(jù)獲取的函數(shù)來(lái)做回調(diào),這部分其實(shí)和 Django 的 django.templatetags.CacheNode 類(lèi)基本一樣。我這邊就寫(xiě)與其不一樣的地方:
class UserCacheNode(Node): """ 優(yōu)雅的自定義模板碎片緩存 """ def __init__(self, nodelist, expire_time_var, fragment_name, vary_on, cache_name, fun=None): # ... self.fun = fun # 用于數(shù)據(jù)獲取的回調(diào)函數(shù) def render(self, context:dict): # ... if value is None: if self.fun: # 實(shí)行回調(diào) context.update(self.fun(*vary_on)) value = self.nodelist.render(context) fragment_cache.set(cache_key, value, expire_time) # 保存至緩存 return value
然后是制作自定義標(biāo)簽:
def get_hot_course(): # 做會(huì)調(diào)用,函數(shù)返回字典 print("call hot course") hot_courses = Course.objects.filter().order_by('stu_nums')[:5] return locals() @register.tag('hot_course_cache') # 自定義的標(biāo)簽名稱(chēng) 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, # 回調(diào)函數(shù) )
然后在模板中就可以這么使用:
{% load course_tag %} {% hot_course_cache 500 hot_courses %} ...hot_courses... {% endcache %}
通過(guò)用自定義標(biāo)簽的方式,就無(wú)需視圖層的參與了,緩存標(biāo)簽的使用方式也和體系中的 cache 相似,由于是自定義的標(biāo)簽,一些 IDE 會(huì)有一些警告,比如我的開(kāi)發(fā)環(huán)境:
運(yùn)行上是沒(méi)問(wèn)題的,IDE 可能對(duì)這類(lèi)自定義標(biāo)簽的支持度不是很好吧。
參考
Custom template tags and filters
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Python爬蟲(chóng)基礎(chǔ)講解之請(qǐng)求
今天帶大家了解一下python爬蟲(chóng)的基礎(chǔ)知識(shí),文中有非常詳細(xì)的解釋說(shuō)明,對(duì)正在學(xué)習(xí)python爬蟲(chóng)的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05為什么Python中沒(méi)有"a++"這種寫(xiě)法
一開(kāi)始學(xué)習(xí) Python 的時(shí)候習(xí)慣性的使用 C 中的 a++ 這種寫(xiě)法,發(fā)現(xiàn)會(huì)報(bào) SyntaxError: invalid syntax 錯(cuò)誤,為什么 Python 沒(méi)有自增運(yùn)算符的這種寫(xiě)法呢?下面小編給大家?guī)?lái)本文幫助大家了解下這方面的知識(shí)2018-11-11python實(shí)現(xiàn)人臉識(shí)別代碼
這篇文章主要介紹了python實(shí)現(xiàn)人臉識(shí)別代碼,還是比較不錯(cuò)的,這里分享個(gè)大家,共需要的朋友參考。2017-11-11安裝并免費(fèi)使用Pycharm專(zhuān)業(yè)版(學(xué)生/教師)
這篇文章主要介紹了安裝并免費(fèi)使用Pycharm專(zhuān)業(yè)版(學(xué)生/教師),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Python實(shí)戰(zhàn)基礎(chǔ)之繪制餅狀圖分析商品庫(kù)存
餅狀圖(pie chart)一般用于描述分類(lèi)型數(shù)據(jù)的相對(duì)頻數(shù)或百分?jǐn)?shù)頻數(shù)分布,呈現(xiàn)部分與總體的關(guān)系,下面這篇文章主要給大家介紹了關(guān)于Python實(shí)戰(zhàn)基礎(chǔ)之繪制餅狀圖分析商品庫(kù)存的相關(guān)資料,需要的朋友可以參考下2022-07-07基于PyTorch實(shí)現(xiàn)一個(gè)簡(jiǎn)單的CNN圖像分類(lèi)器
本文記錄了一個(gè)簡(jiǎn)單的基于pytorch的圖像多分類(lèi)器模型構(gòu)造過(guò)程,參考自Pytorch官方文檔、磐創(chuàng)團(tuán)隊(duì)的《PyTorch官方教程中文版》以及余霆嵩的《PyTorch 模型訓(xùn)練實(shí)用教程》。從加載數(shù)據(jù)集開(kāi)始,包括了模型設(shè)計(jì)、訓(xùn)練、測(cè)試等過(guò)程。2021-05-05