现成包可以参考这里: http://niwibe.github.io/django-jinja/
Requirements
-
Python 2.7, 3.3 or 3.4
-
Django 1.4, 1.5, 1.6 and 1.7
-
jinja2 >= 2.7.0
不过下面的实现没有用到上面的django-jinja 扩展。
不知道随着django版本的演变,又没有吸取jinjia2设计的精华,如果有,那么再手工集成就是多此一举。决定来个性能测试,环境:
win7 家庭版 64bit / python 2.7.3 / django 1.6.5
由于需要页面每次请求都返回不同的内容,因此简单做了个随机数,视图如下:
from django.shortcuts import render
from django.http import HttpResponse
import random
# Create your views here.
def getRandom(req):
return render(req,'testjj.txt',{'r_int':random.randint(1,10000)})
在虚拟机上用ab进行测试:
ab -c 5 -n 1000 http://192.168.1.8:8000/
结果如下:
Concurrency Level: 5
Time taken for tests: 5.021 seconds
Complete requests: 1000
Failed requests: 95
(Connect: 0, Receive: 0, Length: 95, Exceptions: 0)
Write errors: 0
Total transferred: 165895 bytes
HTML transferred: 3895 bytes
Requests per second: 199.18 [#/sec] (mean)
Time per request: 25.103 [ms] (mean)
Time per request: 5.021 [ms] (mean, across all concurrent requests)
Transfer rate: 32.27 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 2
Processing: 17 24 3.9 24 65
Waiting: 15 22 3.7 22 62
Total: 18 25 4.0 24 67
Percentage of the requests served within a certain time (ms)
50% 24
66% 25
75% 26
80% 26
90% 28
95% 29
98% 31
99% 41
100% 67 (longest request)
总时间5.021s。上面没有采用jinjia2, 下面采用jinjia2,代码修改如下,
主要是增加template_loader,ok,先看看django的默认的template loader的逻辑,默认的loader有两个,如下,可以参考这里。
django.template.loaders.filesystem.Loader
django.template.loaders.app_directories.Loader
算法的核心是根据某种规则,计算出模板文件的路径,并read然后decode返回。
from django.template.loader import BaseLoader
from django.template.loaders.app_directories import app_template_dirs
from django.template import TemplateDoesNotExist
from django.core import urlresolvers
from django.conf import settings
import jinja2
class Template(jinja2.Template):
def render(self, context):
# flatten the Django Context into a single dictionary.
context_dict = {}
for d in context.dicts:
context_dict.update(d)
return super(Template, self).render(context_dict)
class Loader(BaseLoader):
is_usable = True
env = jinja2.Environment(loader=jinja2.FileSystemLoader(app_template_dirs))
env.template_class = Template
# These are available to all templates.
env.globals['url_for'] = urlresolvers.reverse
env.globals['MEDIA_URL'] = settings.MEDIA_URL
#env.globals['STATIC_URL'] = settings.STATIC_URL
def load_template(self, template_name, template_dirs=None):
try:
template = self.env.get_template(template_name)
except jinja2.TemplateNotFound:
raise TemplateDoesNotExist(template_name)
return template, template.filename
然后在template_loaders中添加该loader。并重新测试,结果如下:
Time taken for tests: 4.223 seconds
Complete requests: 1000
Failed requests: 100
(Connect: 0, Receive: 0, Length: 100, Exceptions: 0)
Write errors: 0
Total transferred: 165887 bytes
HTML transferred: 3887 bytes
Requests per second: 236.78 [#/sec] (mean)
Time per request: 21.117 [ms] (mean)
Time per request: 4.223 [ms] (mean, across all concurrent requests)
Transfer rate: 38.36 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 2
Processing: 12 20 3.3 20 49
Waiting: 11 18 3.0 17 47
Total: 12 21 3.3 20 50
Percentage of the requests served within a certain time (ms)
50% 20
66% 21
75% 22
80% 23
90% 24
95% 26
98% 29
99% 34
100% 50 (longest request)
可见,总时间少了接近1秒!
对比图如下:
因此,django团队,在这块貌似还是没有采取与jinja2一样的技术或者机制咯。看来大有比较自己集成。