溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么改進(jìn)Django中的模板碎片緩存

發(fā)布時(shí)間:2021-02-08 10:53:16 來(lái)源:億速云 閱讀:352 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹了怎么改進(jìn)Django中的模板碎片緩存,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

起步

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 類基本一樣。我這邊就寫(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)簽名稱
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)境:

怎么改進(jìn)Django中的模板碎片緩存

運(yùn)行上是沒(méi)問(wèn)題的,IDE 可能對(duì)這類自定義標(biāo)簽的支持度不是很好吧。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“怎么改進(jìn)Django中的模板碎片緩存”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI