由于需要解决django template问题,研究了django template结构
一、django tempate 结构
django.tempate是django 模板的封装,主要由两部分构成:
- loader.py 总控入口
- loaders django自定义的一系列Loader,如django.template.loaders.filesystem.Loader
loader.py一些重要的类或者方法
def render_to_string(template_name, dictionary=None, context_instance=None) 入口 ,被shortcuts调用
def get_template(template_name) 被render_to_string调用 ,调用find_template
def find_template(name,dirs=None) 通过settings.TEMPLATE_LOADERS 加载template,被get_template调用
find_template_loader(loader) 通过className实例化loader,被 find_template调用,只要一个名叫load_template_source方法即可。
render_to_string()是template的入口:
def render_to_response(*args, **kwargs): """ Returns a HttpResponse whose content is filled with the result of calling django.template.loader.render_to_string() with the passed arguments. """ httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)} return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
def render_to_string(template_name, dictionary=None, context_instance=None): """ Loads the given template_name and renders it with the given dictionary as context. The template_name may be a string to load a single template using get_template, or it may be a tuple to use select_template to find one of the templates in the list. Returns a string. """ dictionary = dictionary or {} if isinstance(template_name, (list, tuple)): t = select_template(template_name) else: t = get_template(template_name) if not context_instance: return t.render(Context(dictionary)) # Add the dictionary to the context stack, ensuring it gets removed again # to keep the context_instance in the same state it started in. context_instance.update(dictionary) try: return t.render(context_instance) finally: context_instance.pop()
二、 django Template 的性能
django的Template性能非常差,就这么一段code, django 的template能跑10ms(而且blog.cached_tags is None)
{% if blog.cached_tags %} {% if blog.is_buyable %} {% for tag in blog.cached_tags %} <a href="/blogs/item/{{ tag.name|urlencode }}/"> {{ tag.name }} {% if user == sender or user.is_staff %} <u title="删除标签"> </u> {% endif %} </a> {% endfor %} {% else %} {% for tag in blog.cached_tags %} <a href="/blogs/tag/{{ tag.name|urlencode }}/"> {{ tag.name }} {% if user == sender or user.is_staff %} <u title="删除标签"> </u> {% endif %} </a> {% endfor %} {% endif %} {% else %} {% if request.user != blog.sender and not request.user.is_staff %} <b>还没有标签</b> {% endif %} {% endif %}
网上有一份python 各template的测试结果:
funcname: render_django used 0.071762
funcname: render_webpy used 0.015729
funcname: render_bottle used 0.008752
funcname: render_tornado used 0.005675
funcname: render_jinja2 used 0.002073
funcname: render_mako used 0.001627
funcname: render_cheetah used 0.000014
点评一下吧。django就是个渣,不多废话了。webpy的代码很简洁,可惜速度太慢了。bottle看起来快一点,不过也没有多出彩。tornado 本身速度很快,不过模板——也就是如此吧。真的值得一用的,只有jinja2,mako,cheetah三个。速度都小于了5ms,单核每秒可以生成 200个页面,16核机器上大概就能跑到3000req/s,性能比较高。jinja2的速度比较折衷,配置灵活,语法类似django是他的优点。而且 不得不说,jinja2的文档真的很不错。mako的速度比jinja2略快,模板写起来也很舒服。文档略凌乱,可以接受。cheetah的速度——已经 不像是模板了好吧。