`
meiowei
  • 浏览: 147728 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

混合使用django模板和jinja模板

阅读更多

Django一直广受争论的地方就是它的模板功能,其中印象最深的一次是在python-cn上最初由一个与模板不太相关的主题引起的大讨论。

见 《听一个turbogears的家伙讲django该向zope学­什么》

http://groups.google.com/group/python-cn/browse_thread/thread/c32a8ba1b2e1f5f3

 

争论的焦点主要集中在django的模板功能太弱,扩展的filter,tag难写,是否应该在模板中直接允许执行更多的python代码等。

 

Django本身的观点:

Django模板本身从设计之初就更多的考虑到模板的使用者是 页面设计人员 而非 后台程序员 , 所以设计的尽可能简单,从设计上去限制模板的不规范使用,以便更好的区分工作责任,这点从它的模板部分文档从最初就直接分为两份,分别适合以上两种人员进行细读就可以看出来。

 

后台程序员的观点:

或许Django的使用者以后台程序员为主,所以很多人都强烈要求改进Django的模板,以便可以更方便的直接调用python代码。但是Django的开发团队对此要求始终无动于衷。于是出现了其他的一些 模板引擎,比如jinja 。

 

jinja2

jinja的使用上和Django及其相似,都主要通过 {{ }} 和{% %} 这两个东西里进行模板渲染,但是jinja允许你在模板中更多的使用python形式的代码。这在某些时候是的确是非常方便的。同时jinja自己宣称它比django的模板引擎拥有更好的性能。

 

Django中使用jinja2:

目前介绍在Django中使用jinja2的方式主要都是通过各种方式替换Django原有模板。最近看 《Pro Django》,其中第6章介绍模板的时候,提出了另一种在django中使用jinja2的方式。

这种方式是通过自定义一个需要有相应end的tag,然后在render的时候,将此对tag中的原始内容直接传给jinja2进行处理,因此此对tag之间的内容就可以使用jinja的语法,而其他部分仍需符合django的模板语法。这对于只需要少量使用jinja2的情况下,相对于完整替换,这种方式更省时省力,也显得更干净利落。下面就是混合使用django和jinja2的代码示例:

view部分:

# Create your views here.   
from django.http import HttpResponse   
from django.shortcuts import render_to_response   
from django.template import RequestContext   
  
def test(request):   
    user = 'myuser'  
    seq = [1,2,3]   
    def sum(a,b):   
        return a + b   
    return render_to_response('jinja_test.html',    
                              {'user':user, 'seq':seq, 'sum':sum,},    
                              context_instance=RequestContext(request))  

模板代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">  
<html>  
    <head>  
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
        <title>jinja_tag test</title>  
    </head>  
    <body>  
        {%load jinja_tag%}   
        {%jinja%}   
            {% for item in seq - %}   
                {{ item }}   
            {% - endfor %}   
            <br />  
            {{ 1+1*4 }}   
            <br />  
            {{ sum(1, seq[2]) }}   
            <br />  
        {%endjinja%}   
    </body>  
</html> 

 

从上面可以看到,包围在{%jinja%}和{%endjinja%}之间的代码使用jinja语法,而其他部分仍然限制在django的模板语法。

 

实现:

其实实现这样一个jinja tag是非常容易的,具体原理可以看《pro django》原书,这里只贴下经过修改,修复了一些小bug的代码:

import jinja2   
from django import template   
  
register = template.Library()   
  
def string_from_token(token):   
    """  
    Converts a lexer token back into a string for use with Jinja.  
    """  
    if token.token_type == template.TOKEN_TEXT:   
        return token.contents   
    elif token.token_type == template.TOKEN_VAR:   
        return '%s %s %s' % (   
            template.VARIABLE_TAG_START,   
            token.contents,   
            template.VARIABLE_TAG_END,   
        )   
    elif token.token_type == template.TOKEN_BLOCK:   
        return '%s%s%s' % (   
            template.BLOCK_TAG_START,   
            token.contents,   
            template.BLOCK_TAG_END,   
        )   
    elif token.token_type == template.TOKEN_COMMENT:   
        return u'' # Django doesn't store the content of comments  
 
@register.tag   
def jinja(parser, token):   
    """  
    Define a block that gets rendered by Jinja, rather than Django's templates.  
    """  
    bits = token.contents.split()   
    if len(bits) != 1:   
        raise template.TemplateSyntaxError, "'%s' tag doesn't take any arguments." % bits[0]   
  
    # Manually collect tokens for the tag's content, so Django's template   
    # parser doesn't try to make sense of it.   
    contents = []   
    while 1:   
        try:   
            token = parser.next_token()   
        except IndexError:   
            # Reached the end of the template without finding the end tag   
            raise template.TemplateSyntaxError("'endjinja' tag is required.")   
        if token.token_type == template.TOKEN_BLOCK and token.contents == 'endjinja':   
            break  
        contents.append(string_from_token(token))   
    contents = ''.join(contents)   
    return JinjaNode(contents)   
  
class JinjaNode(template.Node):   
    def __init__(self, contents):   
        self.template = jinja2.Template(contents)   
  
    def render(self, context):   
        # Jinja can't use Django's Context objects, so we have to   
        # flatten it out to a single dictionary before using it.   
        jinja_context = {}   
        for layer in context:   
            for key, value in layer.items():   
                if key not in jinja_context:   
                    jinja_context[key] = value   
        return self.template.render(jinja_context)

 

更好的集成:

上面的HTML模板代码中,每次需要使用该 tag 的时候,都要经过 {%load jinja_tag%} 这个步骤,显得很麻烦。

其实可以将该 tag 添加到和django同样的builtin中,那样就可以像使用内置tag一样使用该tag了。

只需要 在 某个app目录下的 __init__.py 文件中添加以下代码就可以实现:

from django.template import add_to_builtins   
# Uncomment the next line to enable the jinja_tag as if defaulttags   
add_to_builtins('jinja_tag.templatetags.jinja_tag') 

 

分享到:
评论

相关推荐

    Python-一个Django模板用于使用Flask作为前端Django作为后端

    这个名为"flango-master"的压缩包文件提供了一个独特的方案,它结合了Python的两个流行框架——Django和Flask,创建了一个后端由Django驱动、前端由Flask呈现的混合应用模式。这样的设计允许开发者充分利用Django的...

    django-render:Django 模板渲染糖。 支持基于功能和类的视图。 (未维护,使用 https

    该包为模板渲染和请求上下文中的 CBV 混合提供装饰器,代码使用简单。 重要提示:所有模板渲染都在请求上下文中进行。 会话、cookies、meta 等可从模板中获得。 安装 您可以通过 pip 安装库。 pip install django...

    python 的django,quixote,uliweb三个web框架

    它具有灵活的URL映射,支持多种模板引擎,包括Mako和Jinja2,以及自己的UliTemplate。Uliweb的ORM可以与多种数据库兼容,包括SQLite、MySQL和PostgreSQL。此外,Uliweb强调插件式设计,使得开发者可以通过安装不同的...

    PyPI 官网下载 | jinjaMarkdown-0.0.4.tar.gz

    Jinja2是基于Python的模板引擎,由Pallets团队开发,它遵循了Django模板语言的设计理念,并引入了许多改进。Jinja2提供了一种清晰、简洁的模板语法,支持变量、控制流、过滤器、宏、继承等功能。它强调代码的可读性...

    计算机毕业设计 BBS问答社区程序使用说明 Python源代码+开发文档说明 软件/插件 范文 模板 素材 项目源码

    5. **模板引擎**:为了呈现动态网页,开发者可能会使用如Jinja2这样的模板引擎,它允许将HTML与Python代码混合,方便地渲染动态内容。 6. **前端技术**:虽然主要讨论的是后端,但前端同样重要。HTML、CSS和...

    django和flask哪个值得研究学习

    Flask的核心是Werkzeug WSGI工具包和Jinja2模板引擎。它的设计思想是保持核心简单,允许开发者根据需要添加各种扩展来实现特定功能,如SQLAlchemy用于数据库操作,Flask-SQLAlchemy简化数据库集成,Flask-WTF用于...

    python-web

    5. **模板引擎**:为了方便动态生成 HTML,Python 框架通常包含模板引擎,如 Django 的 Django Templates 和 Jinja2(Flask 默认使用)。模板引擎允许开发者将 HTML 与 Python 代码混合,动态生成页面内容。 6. **...

    boilerplate:龙卷风样板

    龙卷风样板django、flask 和 tornado 本身风格的混合添加了以下技术会话 (redis) [使用 pycket] Jinja2 模板ORM (mongodb) 【使用原理图和电机】 表单(基于模型)[使用 WTForms] 日志记录WebAssets 充当静态编译器 ...

    最常见的35个Python面试题及答案.docx

    Flask是一个轻量级的Web应用框架,基于Werkzeug WSGI工具箱和Jinja2模板引擎。它允许开发简单的Web应用,同时可以通过扩展支持更复杂的需求。Flask使用了签名cookie来管理会话。 8. **Python内存管理** Python...

    eshop:Python网上商店

    4. **模板系统**:为了创建动态的网页,eshop可能使用了框架提供的模板语言,如Django的模板引擎或Flask的Jinja2。这些模板语言允许开发者将HTML与Python代码混合,以生成动态内容。 5. **购物车功能**:eshop会...

    my-first-blog

    4. **模板引擎**:为了生成动态网页,项目可能会使用如Jinja2这样的模板引擎。模板引擎允许开发者将HTML与Python代码混合,以动态生成页面内容。 5. **HTTP协议和路由设计**:理解HTTP请求和响应是Web开发的基础,...

    Capstone-HashtagSuggestionApp

    开发者可能使用了HTML、CSS和JavaScript,配合Python的模板引擎(如Jinja2)和前端框架(如React或Vue.js),来创建用户友好的交互界面,展示推荐的标签并处理用户的输入。 在实际部署时,应用可能运行在云服务器上...

Global site tag (gtag.js) - Google Analytics