Python+Flask+Jinja2中如何通过子类字符串动态定义变量名引入文件?
问题说明
我定义了一个继承自list的Wrapper类,用来存储文件名FileName和参数名ParamName;另外两个子类ContentA和ContentB继承自Wrapper并扩展了功能,Python代码如下:
class Wrapper(list): def __init__(self, FileName='', ParamName=''): super().__init__() self.FileName=FileName self.ParamName = ParamName class ContentA(Wrapper): def __init__(self, AWrapper): super().__init__('ContentA.html', 'MainContent') self.append(AWrapper) class ContentB(Wrapper): def __init__(self, SomeContent = ''): super().__init__('ContentB.html', 'SubContent') self.Content = SomeContent contB = ContentB('Hello Guys') contA = ContentA(contB) return render_template('index.html', ContA=contA)
在Jinja2模板中,我想通过ContentB的ParamName获取参数名,并用这个名称传递变量给引入的HTML文件,尝试的模板代码如下:
<!-----------------index.html------------------> {% for cont in ContA %} {% with cont.ParamName=cont %} {% include cont.FileName %} {% endwith %} {% endfor %} <!-----------------ContentB.html------------------> <p> {{ SubContent.Content }} </p>
但这个写法没生效,我不想统一变量名,想保留不同名称方便调试,求可行方案。
解决方案
原来的写法失效是因为Jinja2的{% with %}语句不支持用动态变量作为赋值的键名——cont.ParamName会被当成字面量的变量名,而不是解析它的实际值(比如SubContent)。下面两个方法可以解决:
方法1:模板内直接构造动态字典传递
不用改Python代码,直接在模板里用字典字面量语法,把ParamName的值作为键,当前实例作为值传递给引入的模板:
修改index.html:
<!-----------------index.html------------------> {% for cont in ContA %} {% include cont.FileName with {cont.ParamName: cont} %} {% endfor %}
这样ContentB.html里的{{ SubContent.Content }}就能正常获取到Hello Guys的值了。
方法2:Python侧添加上下文生成方法
如果希望后端逻辑更清晰,可以给Wrapper类加一个生成上下文字典的方法:
修改Python代码中的Wrapper类:
class Wrapper(list): def __init__(self, FileName='', ParamName=''): super().__init__() self.FileName=FileName self.ParamName = ParamName def get_context(self): # 返回以ParamName为键、当前实例为值的字典 return {self.ParamName: self}
然后模板里调用这个方法传递上下文:
<!-----------------index.html------------------> {% for cont in ContA %} {% include cont.FileName with cont.get_context() %} {% endfor %}
这个方式把上下文生成的逻辑封装在后端类里,更符合面向对象的设计,也方便后续扩展。
内容的提问来源于stack exchange,提问作者Msnoyce
相关产品推荐
相关产品推荐

