記一次Django項(xiàng)目優(yōu)化

把之前的一個 web 項(xiàng)目重寫了一遍,語言從原先的 PHP 換成 Python,使用了 Django 框架爆阶。項(xiàng)目因?yàn)閿?shù)據(jù)庫比較龐大萌庆,有 600M 左右的 sql 數(shù)據(jù)溶褪,一些應(yīng)用涉及到查詢和修改時,導(dǎo)致網(wǎng)頁操作十分緩慢践险。同時因?yàn)橐彩莿傞_始接觸 Django猿妈,有些代碼寫得比較蠢,后來優(yōu)化之后網(wǎng)頁操作的速度基本可以接受巍虫。故寫這篇文章記錄一下彭则。

模版自定義函數(shù)

因?yàn)閿?shù)據(jù)庫設(shè)計原因,從數(shù)據(jù)庫提取出來的某個字段的數(shù)據(jù)還需要經(jīng)過一次 base64 加密占遥,原先是將篩選出來的 QuerySet 用 for 循環(huán)去遍歷然后修改俯抖。但是,如果直接用 for 循環(huán)去遍歷 QuerySet瓦胎,Django 會把他們?nèi)窟M(jìn)行實(shí)例化芬萍,因?yàn)閿?shù)據(jù)量本身也比較大的原因,會導(dǎo)致占用大量的內(nèi)存搔啊。

因?yàn)槲蚁M诓恍薷臄?shù)據(jù)庫和盡可能少的改動代碼的前提下去解決問題柬祠,一番查閱資料之后發(fā)現(xiàn)自定義 Django 模版的函數(shù)是個不錯的辦法。

Django 模板里面有兩種方式來自定義函數(shù)负芋,分別是 simple_tag 和 filter 方式瓶盛。實(shí)現(xiàn)的方式如下。

在對應(yīng) app 下創(chuàng)建一個名為 templatetags 的目錄(不可修改目錄名),在這個目錄下創(chuàng)建一個名字任意的 py 文件惩猫,在這個 py 文件里導(dǎo)入模板類芝硬,實(shí)例化一個對象 register,然后執(zhí)行一個相應(yīng)的裝飾器即可轧房,文件代碼如下:

from django import template
from django.utils.safestring import mark_safe

register = template.Library()

@register.simple_tag
def base64en(s):
    return base64.b64encode(s.encode('utf-8')).decode("utf-8")

@register.filter
def tobase64(s):
    return base64.b64encode(s.encode('utf-8')).decode("utf-8")

其中拌阴,base64en(simple_tag 方式) 和 tobase64(filter 方式) 是我自定義的函數(shù)。在模版文件里調(diào)用:

{% load addontags %}

{{ sample_str|tobase64 }}
{{ base64en sample_str }}

其中奶镶,addontags 是我定義函數(shù)的 py 文件名迟赃。

兩種實(shí)現(xiàn)模式的區(qū)別為:

  • simple_tag 參數(shù)無個數(shù)限制,而 filter 最多只能有2個參數(shù)
  • simple_tag 不能作為 if 條件厂镇,而 filter 可以
  • simple_tag 后面的參數(shù)之間的空格隨意纤壁,filter 不能有空格

我更傾向 filter 模式,比較好看捺信,嘿嘿酌媒。完成之后打開相應(yīng)頁面,速度得到明顯提升迄靠。

Model 操作優(yōu)化

只獲取需要的數(shù)據(jù)

默認(rèn)情況下秒咨,ORM 查詢的時候會把數(shù)據(jù)庫記錄對應(yīng)的所有列取出,然后轉(zhuǎn)換成 python 對象掌挚,這無疑是個很大的內(nèi)存消耗雨席。當(dāng)我們只需要某些特定列的數(shù)據(jù)時我們可以通過 values()values_list() 函數(shù)來實(shí)現(xiàn),它們會將數(shù)據(jù)轉(zhuǎn)換成 dicts吠式、tuples等而不是復(fù)雜的 python 對象陡厘。

項(xiàng)目中有些 query 查詢,只是用到了部分?jǐn)?shù)據(jù)特占,我們可以通過 values() 函數(shù)簡化結(jié)果糙置。

XModel.objects.filter(xxx=yyy)[:1] # before

XModel.objects.filter(xxx=yyy)[:1].values('zzz') # after

使用 update() 代替 save()

Django 中使用 save() 更新數(shù)據(jù)時,數(shù)據(jù)庫會執(zhí)行兩次操作(select, update)摩钙,而使用 update() 時罢低,數(shù)據(jù)庫只執(zhí)行一次(update)查辩。如果只是更改數(shù)據(jù)而不需要用到查詢結(jié)果胖笛,建議直接換成 update()。

# before
x = XModel.objects.filter(xxx=yyy)
x.zzz = 'aaa'
x.save()

# after
XModel.objects.filter(xxx=yyy).update(zzz='aaa')

使用 create() 代替 save()

同樣的宜岛,Django 中使用 save() 插入數(shù)據(jù)時长踊,數(shù)據(jù)庫會執(zhí)行兩次操作(select, insert),而使用 create() 時萍倡,數(shù)據(jù)庫只執(zhí)行一次(insert)身弊。如果只是為了創(chuàng)建新數(shù)據(jù)到數(shù)據(jù)庫,建議直接換成 create()。

# before
x = XModel(zzz='aaa')
x.save()

# after
XModel.objects.create(zzz='aaa')

使用緩存

在我的 web 項(xiàng)目中阱佛,有幾個頁面其實(shí)不是數(shù)據(jù)讀取特別頻繁的頁面帖汞,這些頁面其實(shí)可以設(shè)置緩存時間,這樣在一段時間內(nèi)用戶訪問時讀取緩存就好了凑术。

因?yàn)榉?wù)器內(nèi)存比較小翩蘸,這里直接使用文件緩存,設(shè)置如下淮逊。

配置文件中:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': os.path.join(BASE_DIR, '.temp'),
    }
}

接著在需要緩存的路徑方法中加入 cache_page 修飾符催首,例如:

@cache_page(86400)
def index(request):
    ...

其中 cache_page 的參數(shù)即為緩存時間,單位為秒泄鹏,86400 即一天郎任。

總結(jié)

因?yàn)轫?xiàng)目比較輕量,沒有涉及到很復(fù)雜的數(shù)據(jù)交互备籽,在完成上述優(yōu)化之后舶治,運(yùn)行速度已經(jīng)可以接受,個人還是比較滿意的:)

注:本作品采用知識共享署名-非商業(yè)性使用-禁止演繹 3.0 未本地化版本許可協(xié)議進(jìn)行許可胶台。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末歼疮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子诈唬,更是在濱河造成了極大的恐慌韩脏,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铸磅,死亡現(xiàn)場離奇詭異赡矢,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)阅仔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門吹散,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人八酒,你說我怎么就攤上這事空民。” “怎么了羞迷?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵界轩,是天一觀的道長。 經(jīng)常有香客問我衔瓮,道長浊猾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任热鞍,我火速辦了婚禮葫慎,結(jié)果婚禮上衔彻,老公的妹妹穿的比我還像新娘。我一直安慰自己偷办,他們只是感情好艰额,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娇澎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天铡溪,我揣著相機(jī)與錄音,去河邊找鬼泪喊。 笑死棕硫,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的袒啼。 我是一名探鬼主播哈扮,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蚓再!你這毒婦竟也來了滑肉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤摘仅,失蹤者是張志新(化名)和其女友劉穎靶庙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娃属,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡六荒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了矾端。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掏击。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖秩铆,靈堂內(nèi)的尸體忽然破棺而出砚亭,到底是詐尸還是另有隱情,我是刑警寧澤殴玛,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布捅膘,位于F島的核電站,受9級特大地震影響族阅,放射性物質(zhì)發(fā)生泄漏篓跛。R本人自食惡果不足惜膝捞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一坦刀、第九天 我趴在偏房一處隱蔽的房頂上張望愧沟。 院中可真熱鬧,春花似錦鲤遥、人聲如沸沐寺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽混坞。三九已至,卻和暖如春钢坦,著一層夾襖步出監(jiān)牢的瞬間究孕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工爹凹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厨诸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓禾酱,卻偏偏與公主長得像微酬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子颤陶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Web框架之Django: (1)簡介: Django是一個由Python寫成開源的重量級Web應(yīng)用框架颗管,采用MT...
    老肖閱讀 3,057評論 0 18
  • 版權(quán): https://github.com/haiiiiiyun/awesome-django-cn Aweso...
    若與閱讀 23,091評論 3 241
  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,938評論 2 89
  • 模塊間聯(lián)系越多,其耦合性越強(qiáng)滓走,同時表明其獨(dú)立性越差( 降低耦合性垦江,可以提高其獨(dú)立性)。軟件設(shè)計中通常用耦合度和內(nèi)聚...
    riverstation閱讀 2,072評論 0 8
  • 元旦三天假搅方,班里好多同學(xué)都回老家了疫粥。由于我們家在鹽城,開車至少八個小時腰懂,媽媽說不方便梗逮,所以就早早的安排了【12.3...
    朱宇恒閱讀 302評論 1 1