如何根据Jinja2模板字段的位置渲染出大小写正确的内容?
如何根据Jinja2模板字段的位置渲染出大小写正确的内容?
嘿,我明白你想要实现的效果——同一个字段在句子开头要大写,在句子中间就保持小写,但之前的方法为啥不管用呢?问题出在你的自定义过滤器上:它是全局检查整个模板有没有字段出现在句首,然后直接返回统一的大写或小写结果,这就导致所有地方的字段都会变成一样的,完全没区分每个字段的具体位置。
那怎么解决这个问题?其实咱们可以换个思路:先把所有字段都渲染成小写,然后再对渲染后的HTML做针对性替换,把那些位于句子开头的字段改成首字母大写。这样就能精准处理每个位置的情况了,具体步骤和代码如下:
解决方案代码
from jinja2 import Environment, from_string import re # 你的模板内容 EXAMPLE_BODY_1 = """ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Example</title> </head> <body> <div><h2>Example Contract Term</h2></div> <div> <p> Sometimes the example_field is in the middle so needs to be lowercase, {{ example_field }} is a good example. </p> <ul> <i>All terms in this example are binding.</i> <i>The terms are made up as this is an example.</i> <i>Terms can always change.</i> </ul> </div> <div><h2>Example Contract Other Term</h2></div> <div> <p> {{ example_field }} can also be at the start of a sentence to therefore needs to be capitalised. </p> <ul> <i>Sometimes it's like the first example.</i> <i>The terms are made up as this is an example.</i> <i>Terms can always change.</i> </ul> </div> </body> </html> """ # 初始化Jinja环境并加载模板 environment = Environment() template = environment.from_string(EXAMPLE_BODY_1) example_merge_field = "pots and pans" # 第一步:先把所有字段渲染成小写版本 rendered_html = template.render(example_field=example_merge_field.lower()) # 第二步:定义要替换的目标字符串 target_lower = example_merge_field.lower() target_capitalized = example_merge_field.capitalize() # 正则匹配两种句子开头的情况: # 1. <p>标签后紧跟的内容(可能带空格) # 2. 句子结束标点(.?!)后紧跟的内容(可能带空格) pattern = re.compile(r'(<p>\s*|\.|\?|!)\s*' + re.escape(target_lower)) # 定义替换规则 def replace_match(match): prefix = match.group(1) # 如果是<p>标签开头,直接拼接大写后的内容;如果是标点,要加个空格 if prefix == '<p>': return f"{prefix}{target_capitalized}" else: return f"{prefix} {target_capitalized}" # 执行替换得到最终HTML final_html = pattern.sub(replace_match, rendered_html) print(final_html)
为什么这个方法管用?
- 先统一渲染成小写,确保句子中间的字段符合要求;
- 用正则精准定位那些位于句子开头的字段:包括段落开头、以及标点后的句子开头;
- 只把这些定位到的字段替换成首字母大写版本,完美区分不同位置的需求。
如果你想用更“原生”的Jinja方式处理,其实也可以给每个字段调用不同的过滤器(句首用{{ example_field|capitalize }},句中用{{ example_field|lower }}),但这种方法需要手动修改模板里的每个字段位置,不如上面的自动替换方法灵活。
备注:内容来源于stack exchange,提问作者Johnny John Boy
相关产品推荐
相关产品推荐

