我想知道在文件中添加包含或宏时是否有任何方法可以使用jinja缩进缩进。我想使用jinja生成代码文件。一个例子是
文件:class.html
class MyClass:
def someOp():
pass
{% include "someOp.html" %}
文件:someOp.html
def someOp2():
pass
模板的结果应为:
class MyClass:
def someOp():
pass
def someOp2():
pass
如果有任何方法让jinja在包含文件中每行的include标记之前添加缩进?或者有没有办法自定义jinja来做到这一点?
答案 0 :(得分:20)
一种方法是将include包装在一个宏中,然后因为宏是一个函数,它的输出可以通过缩进过滤器传递:
class MyClass:
def someOp():
pass
{% macro someop() %}{% include "someOp.html" %}{% endmacro %}
{{ someop()|indent }}
默认情况下,'indent'缩进4个空格并且不缩进第一行,您可以使用例如'indent(8)'进一步缩进,有关详细信息,请参阅http://jinja.pocoo.org/docs/templates/#list-of-builtin-filters。
如果您所包含的内容被定义为开始的宏,则不需要进一步的包装宏,您可以直接跳转到使用缩进过滤器。
答案 1 :(得分:1)
我一直在寻找Jinja2来实现相同的目的,并得出结论,目前无法将多行块缩进与原始Jinja语句对齐。
我在Jinja上发布了一个小型PR,以添加新的语法{%* ... %}
和{{* ... }}
来实现此目的。有关详细信息,请参见PR:
答案 2 :(得分:0)
如果Jinja提供了该设施,将会更加容易。看起来像设施was in the pipeline,但问题已解决(2019年11月20日),并且拉取请求尚未合并,一些技术问题仍需要解决。
以下是目前的解决方案。
auto_indent()
检测主机模板中变量的缩进级别,然后将该缩进应用于一段文本:
import os
import itertools
import jinja2
def indent_lines(text_lines: list, indent: int):
return [' ' * indent + line for line in text_lines]
def matching_line(s, substring):
lineno = s[:s.index(substring)].count('\n')
return s.splitlines()[lineno]
def is_space(c):
return c == ' '
def indentation(line: str) -> int:
initial_spaces = ''.join(itertools.takewhile(is_space, line))
return len(initial_spaces)
def auto_indent(template: str, placeholder: str, content_to_indent: str):
placeholder_line = matching_line(template, '{{ ' + placeholder + ' }}')
indent_width = indentation(placeholder_line)
lines = content_to_indent.splitlines()
first_line = [lines[0]] # first line uses placeholder indent-- no added indent
rest = indent_lines(lines[1:], indent_width)
return os.linesep.join(first_line + rest)
示例:
action_class = """\
class Actions:
def __init__(self):
pass
def prequel(self):
pass
{{ methods }}
def sequel(self):
pass
"""
inserted_methods = """\
def create_branch():
pass
def merge_branch():
pass
"""
if __name__ == '__main__':
indented_methods = auto_indent(action_class, 'methods', inserted_methods)
print(jinja2.Template(action_class).render(methods=indented_methods))
示例输出:
>>> python indent.py
class Actions:
def __init__(self):
pass
def prequel(self):
pass
def create_branch():
pass
def merge_branch():
pass
def sequel(self):
pass
对于3.6之前的Python版本,请删除函数参数的类型提示。