在Jinja2中,我希望通过运行以下内容来使其看起来像应该的那样工作:
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('x.html')
print template.render()
本质上,目标是<head>
使用aa{% call js() %} /* some js */ {% endcall %}
宏将所有javascript合并到标签中。
<html>
<head>
<script type="text/javascript>
{% block head_js %}{% endblock %}
</script>
</head>
<body>
{% include "y.html" %}
</body>
</html>
{% macro js() -%}
// extend head_js
{%- block head_js -%}
{{ super() }}
try { {{ caller() }} } catch (e) {
my.log.error(e.name + ": " + e.message);
}
{%- endblock -%}
{%- endmacro %}
Some ... <div id="abc">text</div> ...
{% call js() %}
// jquery parlance:
$(function () {
$("#abc").css("color", "red");
});
{% endcall %}
当我通过jinja2运行X.html时,我希望结果是:
<html>
<head>
<script type="text/javascript>
try { {{ $("#abc").css("color", "red"); }} } catch (e) {
usf.log.error(e.name + ": " + e.message);
}
</script>
</head>
<body>
Some ... <div id="abc">text</div> ...
</body>
</html>
实际结果并不令人鼓舞。我遇到了两种可能的照明错误,例如:
TypeError:宏“ js”不带关键字参数“ caller”
或者,当我尝试添加另一个基本宏时,例如
{% macro js2() -%}
{%- block head_js -%}
// ... something
{%- endblock -%}
{%- endmacro %}
我得到以下异常
jinja2.exceptions.TemplateAssertionError:块’head_js’定义了两次
我觉得好像遇到了关于block
标签优先于标签的设计问题macro
(即宏似乎没有按照我期望的方式封装块标签)。
我想我的问题很简单:
Jinja2可以做我想做的事吗?如果是这样,怎么办?
如果不是,是否有另一个基于Python的模板引擎支持这种模式(例如mako,genshi等),该模式在Google App Engine中不会出现问题
感谢您的阅读-感谢您的投入。
布赖恩
我正在尝试编写扩展程序来解决此问题。我到一半了-使用以下代码:
from jinja2 import nodes, Environment, FileSystemLoader
from jinja2.ext import Extension
class JavascriptBuilderExtension(Extension):
tags = set(['js', 'js_content'])
def __init__(self, environment):
super(JavascriptBuilderExtension, self).__init__(environment)
environment.extend(
javascript_builder_content = [],
)
def parse(self, parser):
"""Parse tokens """
tag = parser.stream.next()
return getattr(self, "_%s" % str(tag))(parser, tag)
def _js_content(self, parser, tag):
""" Return the output """
content_list = self.environment.javascript_builder_content
node = nodes.Output(lineno=tag.lineno)
node.nodes = []
for o in content_list:
print "\nAppending node: %s" % str(o)
node.nodes.extend(o[0].nodes)
print "Returning node: %s \n" % node
return node
def _js(self, parser, tag):
body = parser.parse_statements(['name:endjs'], drop_needle=True)
print "Adding: %s" % str(body)
self.environment.javascript_builder_content.append(body)
return nodes.Const('<!-- Slurped Javascript -->')
env = Environment(
loader = FileSystemLoader('.'),
extensions = [JavascriptBuilderExtension],
)
这样可以很容易地将Javascript添加到模板的末尾…例如
<html>
<head></head>
<body>
{% js %}
some javascript {{ 3 + 5 }}
{% endjs %}
{% js %}
more {{ 2 }}
{% endjs %}
<script type="text/javascript">
{% js_content %}
</script>
</body>
</html>
运行env.get_template('x.html').render()
将产生一些启发性的注释以及预期的输出结果:
<html>
<head>
<script type="text/javascript>
</script>
</head>
<body>
<!-- Slurped Javascript -->
<!-- Slurped Javascript -->
<script type="text/javascript">
some javascript 8
more 2
</script>
</body>
</html>
当然,这与希望的脚本不同,但至少可以方便地将其合并到一个位置。
但是,该解决方案并不完整,因为在其中有一个{% include "y.html" %}
“ y.html”包含一条{% js %}
语句的情况下,{% js_content %}
gets在包含{% js %}
语句之前被调用(即x.html
在y.html
开始之前已被完全解析)。
我还需要但尚未插入具有静态javascript的常量节点,try/catch
我已表示要在其中包含。这不是问题。
我很高兴取得进步,并感谢您的投入。
我打开了一个相关的问题:包含之后的Jinja2编译扩展
解
class JavascriptBuilderExtension(Extension):
tags = set(['js'])
def __init__(self, environment):
super(JavascriptBuilderExtension, self).__init__(environment)
environment.extend(jbc = "",)
def parse(self, parser):
"""Parse tokens """
tag = parser.stream.next()
body = parser.parse_statements(['name:endjs'], drop_needle=True)
return nodes.CallBlock(
self.call_method('_jbc', [], [], None, None),
[], [], body
).set_lineno(tag.lineno)
def _jbc(self, caller=None):
self.environment.jbc += "\ntry { %s } catch (e) { ; };" % caller()
return "<!-- Slurped -->"
完成后,环境将包含jbc
具有所有Javascript的变量。我可以通过插入string.Template
。
从我的评论:
如果您使用扩展而不是包含,则可以这样做。但是由于解析和渲染步骤之间完全分开,因此直到为时已晚,您才能更改父作用域的上下文。同样,Jinja上下文应该是不可变的。
例:
base.html
<html>
<head>
{% block head %}
<title>{% block title %}This is the main template{% endblock %}</title>
<script type="text/javascript">
{% block head_js %}
$(function () {
$("#abc").css("color", "red");
});
{% endblock %}
</script>
{% endblock head_js %}
</head>
<body>
{% block body %}
<h1>{% block body_title %}This is the main template{% endblock body_title %}</h1>
{% endblock body %}
</body>
</html>
some_page.html
{% block title %}This is some page{% endblock title %}
{% block head_js %}
{{ super() }}
try { {{ caller() }} } catch (e) {
my.log.error(e.name + ": " + e.message);
} // jquery parlance:
{% endblock head_js %}
问题内容: 我正在为使用Jinja模板的服务器使用Flask微框架。 我有一个家长和孩子们的一些所谓的模板和,这些孩子有的模板是相当大的HTML文件,我想以某种分裂他们超过我的工作更好的洞察力。 我的脚本内容: The magic is in : 魔力在于child1.html: 而不是评论: 我有很多html文本,很难跟踪更改并且不犯一些错误,因此很难查找和纠正。 我只想加载而不是全部写入。 我
问题内容: 我正在使用LiteIDE for Go。我的Go文件位于此处: 当我使用以下文件添加文件时: 导入“ ../Helper” 我收到此错误: 无法加载软件包:/Users/username/go/src/src/projectA/main.go:4:8:非本地软件包中的本地导入“ ../Helper” 有什么想法我做错了吗? 问题答案: 您通过导入路径导入软件包。对于位于中的packag
我创建了一个spring boot应用程序,它读取一个excel文件,以便在前端显示数据,因此基本上它是持久数据的来源。我能够从eclipse正确地运行,但是当我创建一个spring boot jar并从命令行运行它时,它会失败,因为jar中没有包含文件。 我尝试了两个位置src/main/resources和/src/main/webapp/WEB-INF/external/,但在这两种情况下都
问题内容: 我正在为JEE5 Web服务编写单元测试。Web服务的行为取决于文件中设置的属性。因此,我想将我分成一个恒定的部分和一个在两次测试之间更改的部分。 为了查看是否确实可行,我尝试查看是否可以拆分该属性。根据一些说明,我发现了以下几点: web.xml fragment.xml 但是,我在文件上收到验证错误: 必须为元素类型“ web-app”声明属性“ version”。[7] 必须为元
问题内容: 我正在为Joomla编写模块,这时我真的需要能够使用Jfactory连接到数据库。通常一个人可以简单地使用,但是PHP错误告诉我不包含JFactory类。 所以现在我需要知道如何包括这个JFactory类 。我尝试了一些在互联网上发现的建议,但都没有成功。这是代码(独立运行时完美) 希望您能解决我的问题。您的帮助将不胜感激。 尝试1 但这也不起作用。 尝试2(成功) 现在一切正常。
我有一个结构如下的maven项目: 我希望maven jar插件在构建jar文件时打包到数据库文件夹中。我尝试过包含这里概述的内容:https://maven.apache.org/plugins/maven-jar-plugin/examples/include-exclude.html,但它找不到目录“../database”(或../../database或../../../database
问题内容: 我有一个包含几个JavaScript函数的JavaScript文件(extension ,不是)。 我想从一个JavaScript函数中仅包含几个PHP函数的PHP文件中调用其中一个PHP函数。 那可能吗? 我需要在文件中“包含” 包含PHP函数的文件吗? 我该怎么办? 例如,假设我有一个名为myLib.php的文件,其中包含一个带有两个参数(和)的函数。然后,我有一个包含名为的函数的
问题内容: PEP8有一个关于将导入置于文件顶部的规则: 导入总是放在文件的顶部,紧随任何模块注释和文档字符串之后,以及模块全局变量和常量之前。 但是,在某些情况下,我可能想做些类似的事情: 在这种情况下,命令行实用程序会标记我的代码: E402模块级别导入不在文件顶部 通过修改达到PEP8的最佳方法是什么? 为什么 我有这段代码,因为我遵循的是《The Hitchhiker’s Guide to