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_layui后台模板
Heroicons 在Django和Jinja模板中使用 。要求支持Python 3.6至3.9。 支持Django 2.2到3.2。 你的考试慢吗? 查看我的《一书,其中涵盖了许多最佳实践,因此您可以编写更快,更准确的测试。用法heroicons软件包同时...
django项目及环境搭建好后,创建模板文件。
一个Django模板,用于使用Flask作为前端,Django作为后端
pyjade, Django Jinja2和Mako的Jade 模板系统 PyJade PyJade是 python的一个高性能端口,它将任何. jade 源转换为每个模板语言( 。Django,Jinja2,Mako或者 Tornado ) 。命令行实用程序要简单地将转换输出到控制台...
Jinja2模板引擎 安装Jinja2 :pip install jinja2,在应用目录下添加jinja2_env.py设定环境变量。 from django.contrib.staticfiles.storage import staticfiles_storage from django.urls import reverse from ...
django整合jinja与sqlalchemy
URL映射:Django使用URL映射机制将请求的URL地址与相应的处理函数进行匹配,从而实现灵活的URL路由和页面跳转。 模板引擎:Django的模板引擎提供了一种简单而强大的方式来生成动态的HTML页面。它支持模板继承、变量...
jinja, Jinja2模板引擎 Jinja2Jinja2是用纯 python 编写的模板引擎。 它提供了一个 Django 激发非xml语法,但支持内联表达式和可选的沙箱。下面是Jinja模板的一个小示例:{% extends 'base.html' %}
Django入门基础教程:django模板 Django入门基础教程:django模板
一套精美的博客模板 ,适用于各种后台,如果要是用django开发,可以参考追梦任务的博客:https://www.zmrenwu.com/post/2/
打算做网站左边栏的二级链接,通过从数据库外联键(ForeignKey)获取子节点,再使用Django模板{% for <个体> in <父节点>.<个体所在表名>_set.all %}产生第二季链接。 但该模板还存在渲染错误,会出现子节点渲染后的父...
项目标题:高效 Django 模板引擎开发源码集合 技术栈:主要采用 Python 语言进行开发。 包含文件类型:共计 36 个文件,其中包括: - Python 源代码文件(.py):31 个 - 文本文件(.txt):2 个 - Git 忽略配置(....
今天小编就为大家分享一篇更换Django默认的模板引擎为jinja2的实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
从新手角度记录django前端模板应用和crispy form有关内容,涉及bootstrap4框架,自定义用户密码修改和重置等。详细记录了settings文件及url匹配,对Django的forms和自带的views进行了简单应用于修改。
使用Django开发的天天生鲜商城源码 使用Django开发的天天生鲜商城源码 使用Django开发的天天生鲜商城源码 使用Django开发的天天生鲜商城源码 使用Django开发的天天生鲜商城源码 使用Django开发的天天生鲜...