首页 > Python > 在django中使用jinja2模板
201211月12

在django中使用jinja2模板

起因

      django算的上是用的人最多的python框架了,特别是在网站开发方面,他的大而全的确可以为开发者节省大量的开发时间。然而django的模板是一直让人诟病的地方,可能是为了实现严格的m-v-t(model-view-template),django自带的模板有很强的限制,虽然也提供了扩展方式,例如tag,filter,但却还是给人以不简洁的感觉。

解决

      django从1.2开始,提供了集成第三方的模板的接口,我们只需要扩展这些接口,就可以非常方便地使用第三方模板,当然之前的版本也可以通过修改render_to_response等来实现替换模板,但是既然有了更方便的方式,那就没有理由继续使用原来那种费力不讨好的方式了,所以我们这里只介绍扩展django接口的方式来集成jinja2。根据django的官方文档介绍,我们只要实现两个接口,一个是Template类,用来解析模板,我们要实现它的render()方法,另一个是Loader类,通过实现它的load_template方法,来定义如何查找模板位置。
       下面发一个我修改的集成文件

# django_jinja2.py
# -*- coding: utf-8 -*-
"""
See http://docs.djangoproject.com/en/dev/ref/templates/api/#using-an-alternative-template-language
Set https://gist.github.com/472309

To use:
* Add this template loader to settings: `TEMPLATE_LOADERS`
* Add template dirs to settings: `TEMPLATE_DIRS`

If in template debug mode - we fire the template rendered signal, which allows
debugging the context with the debug toolbar. Viewing source currently doesnt
work.

If you want {% url %} or {% csrf_token %} support I recommend grabbing them
from Coffin (http://github.com/dcramer/coffin/blob/master/coffin/template/defaulttags.py)
Note for namespaced urls you have to use quotes eg:
{% url account:login %} => {% url "account:login" %}
"""
import os, sys
from django.conf import settings
from django.core import urlresolvers
from django.core.exceptions import ImproperlyConfigured
from django.template import TemplateDoesNotExist, Origin
from django.template.loader import BaseLoader
from django.utils.importlib import import_module
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)

        if settings.TEMPLATE_DEBUG:
            from django.test import signals
            self.origin = Origin(self.filename)
            signals.template_rendered.send(
                sender=self, 
                template=self, 
                context=context
            )

        return super(Template, self).render(context_dict)


# Get from django.template.loaders.app_directories.Loader
# At compile time, cache the directories to search.
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
app_template_dirs = []
for app in settings.INSTALLED_APPS:
    try:
        mod = import_module(app)
    except ImportError, e:
        raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
    template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
    if os.path.isdir(template_dir):
        app_template_dirs.append(template_dir.decode(fs_encoding))

class App_Directoriesloader(BaseLoader):
    # whether the loader can be used in this Python installation.
    is_usable = True

    # Set up the jinja env and load any extensions you may have
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(app_template_dirs))
    env.template_class = Template

    # These are available to all templates.
    env.globals['BASE_URL'] = settings.BASE_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)
            return template, template.filename
        except jinja2.TemplateNotFound:
            raise TemplateDoesNotExist(template_name)

      它的前身是一个外国友人写的,原来他是定义了一个JINJA2_TEMPLATE_DIRS变量来存放所有要加载模板的路径,我考虑到想把所有的功能切分成app来实现,因此将其改成自动加载每个已安装app中的templates目录。
       当然最后我们还要在settings.py的TEMPLATE_LOADERS中加入我们的Loader类:

TEMPLATE_LOADERS = (
    # Project load by app which in INSTALLED_APPS
    'perf_tool_web.django_jinja2.App_Directoriesloader',
)

      这样我们就可以用jinja2的语法来写我们的模板了,开始享受不一样的快乐(^O^)。

文章作者: iitshare
本文地址:http://www.iitshare.com/django-jinja2-template.html
版权所有 © 转载时必须以链接形式注明作者和原始出处!

更多
本文目前尚无任何评论.

发表评论