记一次Django项目优化

把之前的一个 web 项目重写了一遍,语言从原先的 PHP 换成 Python,使用了 Django 框架。项目因为数据库比较庞大,有 600M 左右的 sql 数据,一些应用涉及到查询和修改时,导致网页操作十分缓慢。同时因为也是刚开始接触 Django,有些代码写得比较蠢,后来优化之后网页操作的速度基本可以接受。故写这篇文章记录一下。

模版自定义函数

因为数据库设计原因,从数据库提取出来的某个字段的数据还需要经过一次 base64 加密,原先是将筛选出来的 QuerySet 用 for 循环去遍历然后修改。但是,如果直接用 for 循环去遍历 QuerySet,Django 会把他们全部进行实例化,因为数据量本身也比较大的原因,会导致占用大量的内存。

因为我希望在不修改数据库和尽可能少的改动代码的前提下去解决问题,一番查阅资料之后发现自定义 Django 模版的函数是个不错的办法。

Django 模板里面有两种方式来自定义函数,分别是 simple_tag 和 filter 方式。实现的方式如下。

在对应 app 下创建一个名为 templatetags 的目录(不可修改目录名),在这个目录下创建一个名字任意的 py 文件,在这个 py 文件里导入模板类,实例化一个对象 register,然后执行一个相应的装饰器即可,文件代码如下:

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 方式) 是我自定义的函数。在模版文件里调用:

{% load addontags %}

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

其中,addontags 是我定义函数的 py 文件名。

两种实现模式的区别为:

  • simple_tag 参数无个数限制,而 filter 最多只能有2个参数
  • simple_tag 不能作为 if 条件,而 filter 可以
  • simple_tag 后面的参数之间的空格随意,filter 不能有空格

我更倾向 filter 模式,比较好看,嘿嘿。完成之后打开相应页面,速度得到明显提升。

Model 操作优化

只获取需要的数据

默认情况下,ORM 查询的时候会把数据库记录对应的所有列取出,然后转换成 python 对象,这无疑是个很大的内存消耗。当我们只需要某些特定列的数据时我们可以通过 values()values_list() 函数来实现,它们会将数据转换成 dicts、tuples等而不是复杂的 python 对象。

项目中有些 query 查询,只是用到了部分数据,我们可以通过 values() 函数简化结果。

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

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

使用 update() 代替 save()

Django 中使用 save() 更新数据时,数据库会执行两次操作(select, update),而使用 update() 时,数据库只执行一次(update)。如果只是更改数据而不需要用到查询结果,建议直接换成 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() 插入数据时,数据库会执行两次操作(select, insert),而使用 create() 时,数据库只执行一次(insert)。如果只是为了创建新数据到数据库,建议直接换成 create()。

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

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

使用缓存

在我的 web 项目中,有几个页面其实不是数据读取特别频繁的页面,这些页面其实可以设置缓存时间,这样在一段时间内用户访问时读取缓存就好了。

因为服务器内存比较小,这里直接使用文件缓存,设置如下。

配置文件中:

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 的参数即为缓存时间,单位为秒,86400 即一天。

总结

因为项目比较轻量,没有涉及到很复杂的数据交互,在完成上述优化之后,运行速度已经可以接受,个人还是比较满意的:)

注:本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 未本地化版本许可协议进行许可。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • Web框架之Django: (1)简介: Django是一个由Python写成开源的重量级Web应用框架,采用MT...
    老肖阅读 3,002评论 0 18
  • 版权: https://github.com/haiiiiiyun/awesome-django-cn Aweso...
    若与阅读 22,836评论 3 242
  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,789评论 2 89
  • 模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。软件设计中通常用耦合度和内聚...
    riverstation阅读 2,020评论 0 8
  • 元旦三天假,班里好多同学都回老家了。由于我们家在盐城,开车至少八个小时,妈妈说不方便,所以就早早的安排了【12.3...
    朱宇恒阅读 263评论 1 1