本问题已经有最佳答案,请猛点这里访问。
我在Python变量中有以下HTML模板:
template ="""
function work()
{
alert('bla');
}
Success rate is {value:.2%} percent.
"""
我想用一些带有适当格式的十进制数替换{value:.2%}。由于我的模板可能包含大量JavaScript代码,因此我希望避免使用{{和}}转义大括号,因此不能直接使用template.format(...)。
使用Template(template).substitute(...)似乎也不可能,因为我想要value的高级格式化。
我可以用相应的%(value)...语法替换{value:.2%},然后使用template % ...。但我不喜欢这种语法,因为真实世界模板中的大多数变量都不需要高级格式化,所以我想保持占位符语法简单。
所以我的问题是,是否可以在模板中使用自定义占位符,以便在必要时进行高级格式化,即只需{{value}}或[[value]],还可以{{value:.2%}}或[[value:.2%]]?
编辑:最后,我想避免当模板包含占位符(例如{{dont_want_this_substituted}})时.format(...)会产生的错误,传递的字典不包含值。也就是说,我只想替换某些占位符,而不是替换模板中出现的所有占位符。
编辑2:为了实现我想要的,我可以先用正则表达式获取所有占位符,然后格式化它们的内容,最后在模板中进行替换。但我想知道是否存在更简单的解决方案。
编辑3:有人建议我拆分模板以避免format()出现问题。但是,我想避免这种情况,因为模板实际上来自一个文件。
是否无法预先格式化您的值?
@CodyGuldner我可以,但我想在模板中指定格式。 我可以使用正则表达式获取所有占位符,然后通过首先格式化它们的内容来替换它们,但我想知道是否存在更简单的解决方案。 生病编辑问题以澄清这一点。
为什么不拥有多个文件? 或者只是单独存储模板。
另请参阅:自定义placholder语法
只需预处理模板即可。 例如,如果希望[[...]]成为模板标记并单独保留单个{和}字符:
template ="""
function work()
{
alert('bla');
}
Success rate is [[value:.2%]] percent.
"""
result = template.replace("{","{{").replace("}","}}").replace("[[","{").replace("]]","}").format(value=0.8675309)
尝试使用不同数量的大括号来完成所有操作都很棘手,所以我肯定会使用其他一些字符。 但是,小心的是,[[和]]之类的东西可能合理地出现在合法的JavaScript代码中。 可能更好地使用从未有过的东西。
谢谢,这确实是一个选择。 虽然如果我想使用{{...}}作为占位符,但是可能需要一些正则表达式替换,这有点棘手。 不知道有没有更好的方法呢? 我还编辑了原始问题,要求只能替换某些占位符。
在这种情况下,您将要编写自己的模板引擎。
*另见:stackoverflow.com/a/41231617/42223 ;; 对于使用自定义类扩展str.format()方法的解决方案。
忘记正则表达式和预处理。 您应该分解模板,以便变量部分与部分不在同一个字符串中。
head ="""
function work()
{
alert('bla');
}
"""
template ="""
{head}
Success rate is {value:.2%} percent.
"""
Finally, I want to avoid errors that .format(...) would produce when the template contains placeholders, such as {{dont_want_this_substituted}}, for which the passed dictionary doesn't contain a value. That is, I want to only substitute only certain placeholders, not all that appear in the template.
这可能是hacky,但你可以使用collections.defaultdict,如本答案所示。 来自该答案的代码示例(已修改)。
from collections import defaultdict
my_csv = '{optional[first]},{optional[middle]},{optional[last]}'
print( my_csv.format( optional=defaultdict(str, first='John', last='Doe') ) )
我想避免拆分模板,因为它来自一个文件。 我将更新问题以澄清这一点。