【问题标题】:Python Jinja2 template render with stringPython Jinja2 模板用字符串渲染
【发布时间】:2018-07-29 15:46:53
【问题描述】:

我正在尝试使用 Jinja2 呈现 html 模板 - 放入从 Pandas 数据帧中提取的变量值。目前我将变量硬编码到render 命令中,如下所示:

template_loader = jinja2.FileSystemLoader(searchpath=template_dir)
template_env = jinja2.Environment(loader=template_loader)
template_file = "report.html"
template = template_env.get_template(template_file)
html_code = template.render(reg=reg.iat[0, 0], ac=ac.iat[0, 0],
                            su_new=su_new.iat[0, 0], chu_new=chu_new.iat[0, 0],
                            title_0=play.iat[0, 0], title_0_count=play.iat[0, 1],
                            title_1=play.iat[1, 0], title_1_count=play.iat[1, 1],
                            title_2=play.iat[2, 0], title_2_count=play.iat[2, 1])

问题是有时,“播放”数据帧中没有第 3 行,这会返回索引错误(因为那里没有元素)。

我已经创建了一个循环来准备变量,可以将其插入到render命令中,如下所示:

template_variables = "reg=reg.iat[0, 0], ac=ac.iat[0, 0],su_new=su_new.iat[0, 0], chu_new=chu_new.iat[0, 0], "

for i in range(play.shape[0]):
    template_variables += str("title_" + str(i) + "=play.iat[" + str(i) + ", 0], title_" + str(i) + "_count=play.iat[" + str(i) + ", 1], ")

template_variables = template_variables.rstrip(", ")

template_loader = jinja2.FileSystemLoader(searchpath=template_dir)
template_env = jinja2.Environment(loader=template_loader)
template_file = "report.html"
template = template_env.get_template(template_file)
html_code = template.render(template_variables)

这样,我收到以下错误:

ValueError: 字典更新序列元素#0 的长度为 1; 2 是必需的

我想这背后的原因是我创建了一个字符串,它不能在 Jinja2 render 命令中使用。知道是否有可能将字符串传递给该命令,或者我是否必须找到另一种方法来解决基于 Dataframe 大小提取元素的问题?

谢谢你和最好的问候, 博斯扬

【问题讨论】:

    标签: python templates jinja2 render


    【解决方案1】:

    我做了一些挖掘并想出了解决方案。我在这里发布它以防其他人遇到类似问题。 正如预期的那样,问题是它是一个字符串。所以最初我准备了相同的字符串(将“,”更改为“|”作为分隔符,“,”也包含在iat命令中)。然后我用字符串创建了字典并在template.render() 中使用它。 下面是代码:

    template_variables = "reg=" + str(reg.iat[0, 0]) + "|ac=" + str(ac.iat[0, 0]) + "|su_new=" + str(su_new.iat[0, 0]) + "|chu_new=" + str(chu_new.iat[0, 0]) + "|"
    
    for i in range(play.shape[0]):
        template_variables += "title_" + str(i) + "=" + str(play.iat[i, 0]) + "|title_" + str(i) + "_count=" + str(play.iat[i, 1]) + "|"
    
    template_variables = template_variables.rstrip("|")
    template_variables = dict(map(lambda variable: variable.split('='), template_variables.split('|')))
    
    template_loader = jinja2.FileSystemLoader(searchpath=template_dir)
    template_env = jinja2.Environment(loader=template_loader)
    template_file = "report.html"
    template = template_env.get_template(template_file)
    html_code = template.render(template_variables)
    

    可能不是最优雅的方式,但它似乎可以解决问题。

    最好的问候, 博斯扬

    【讨论】:

    • 我发现的另一种方法是简单地将 df.as_matrix() 输入到渲染函数中,然后在 html 模板本身中添加“for”循环。
    【解决方案2】:

    您可以使用文字轻松地创建一个字典,而不是使用所有魔法从字符串构造字典:

    template_variables = dict(
        reg=reg.iat[0, 0],
        ac=ac.iat[0, 0],
        su_new=su_new.iat[0, 0],
        chu_new=chu_new.iat[0, 0],
        titles=[
            {"name": play_iat[i,0], "count": play_iat[i,1]}
            for i in range(len(play_iat))
        ]
    )
    
    html_code = template.render(template_variables)
    

    在模板中,您将引用regacsu_newchu_new 变量像往常一样(例如{{ reg }}),然后使用类似下面的内容来列出 titles 变量:

    {% for title in titles %}
        Name: {{ title.name }}, Count: {{ title.count }}
    {% endfor %}
    

    dict 构造函数中的 titles 条目中的特殊魔法是列表推导式, 它根据您指定的序列中的项目建立一个事物列表(在这种情况下,整数索引到play_iat。)所以每次理解获取 range 序列中的一个整数,它从这些片段中构造另一个字典 play_iat 指定的,并将该字典添加到它正在构建的列表中。那么它 将列表放入titles 键下的外部dict

    模板在for循环中引用titles的列表,抓取每个并放置 将其放入item 变量中,您可以在其中使用点语法引用相应内部字典的namecount 字段。

    【讨论】:

      猜你喜欢
      • 2018-08-19
      • 2015-01-06
      • 2017-03-01
      • 2015-05-05
      • 2014-12-23
      • 1970-01-01
      • 2012-02-17
      • 2017-10-04
      • 1970-01-01
      相关资源
      最近更新 更多