在Jinja2 / Werkzeug中渲染python dict

时间:2013-10-02 15:46:39

标签: python werkzeug jinja2

我正在玩一个url shortener(基于Werkzeug的Shortly演示应用程序)。

我有这样的字典 -

    ('1', {'target': 'http://10.58.48.103:5000/', 'clicks': '1'})
    ('3', {'target': 'http://slash.org', 'clicks': '4'})
    ('2', {'target': 'http://10.58.48.58:5000/', 'clicks': '1'})
    ('5', {'target': 'http://de.com/a', 'clicks': '0'})

在url_list中返回并由render_template

使用
def on_list_urls(self, request):
    url_list = self.get_urls()
    return self.render_template('list_urls.html',
        url_list = url_list
    )

模板list_urls非常简单 -

    {% extends "layout.html" %}
    {% block title %}List URLs{% endblock %}
    {% block body %}
      <h2>List URLs</h2>
      <ul id="items">
      {% for item in url_list %}
        <li>{{ item }}</li>
      {% endfor %}
      </ul>

    {% endblock %}

事情是,我似乎无法访问dict中的项目。

该行

<li>{{ item }}</li>

是我关注的焦点。如上所述,我得到了dict中的键列表。

<li>{{ item["target"] }}</li>

什么都不返回。没有任何一个     {{user.url}}“&gt; {{user.username}} 文档中的类型东西似乎有效。

想法好吗?新手 - 要温柔。感谢。

更新

感谢您的回复。

Ewan的答案有效,但使用了一系列的词组。我想传递一个dict并渲染它(因为我想要一个非整数的项目索引)。 Jinja那样做吗?

另外 - 我错误地表示了url_list。它更像是这样 -

{'a': {'target': 'http://testing.com/test', 'clicks': '0'}, 
'1': {'target': 'http://10.58.48.103:5000/', 'clicks': '1'}, 
'3': {'target': 'http://slash.org', 'clicks': '4'}, 
'2': {'target': 'http://10.58.48.58:5000/', 'clicks': '1'}}

进一步的实验 - 传递dict会产生关于列表对象的错误。

   {% for key in url_list.iteritems() %}

    UndefinedError: 'list object' has no attribute 'iteritems'

再次感谢。

仍然感到困惑的是,为什么它认为我正在通过一个清单但现在已经开始工作了。

{% for key, value in url_list.iteritems() %}
    <li>{{ key }} - {{ value["target"] }} - {{ value["clicks"] }}</li>

打印出所有内容。非常感谢。

3 个答案:

答案 0 :(得分:26)

您的url_list应如下所示:

url_list = [{'target': 'http://10.58.48.103:5000/', 'clicks': '1'}, 
            {'target': 'http://slash.org', 'clicks': '4'},
            {'target': 'http://10.58.48.58:5000/', 'clicks': '1'},
            {'target': 'http://de.com/a', 'clicks': '0'}]

然后使用:

<li>{{ item["target"] }}</li> 

在您的模板中可以使用。

编辑1:

你的模板认为你正在传递一个列表,所以你确定你传递的是你的原始词典,而不是我上面的列表吗?

此外,您需要同时访问字典中的keyvalue(当您传递字典而不是列表时):

Python 2.7

{% for key, value in url_list.iteritems() %}
    <li>{{ value["target"] }}</li> 
{% endfor %}

Python 3

{% for key, value in url_list.items() %}
    <li>{{ value["target"] }}</li> 
{% endfor %}

答案 1 :(得分:0)

请注意,{2}和Python 3中都存在dict.items()方法。但该方法不对有关字典中包含的订单项进行迭代提供保证。这就是为什么使用字典列表而不是像上面所说的字典字典这个例子更有意义。

答案 2 :(得分:0)

一种方法是将处理逻辑与HTML完全分开。因此,将HTML放在单独的文件中,例如top.reddit.html。但是HTML中的内容是动态的,因为它是从Reddit中提取的。因此,我们使用Jinja2作为模板引擎。这意味着top.reddit.html只是模板,而不是要提供的最终内容。

top.reddit.html(为简洁起见,此处仅显示动态行):

{% for item in data %}
<tr>
  <td width="0%">&nbsp;</td>
  <td>{{item["date"]}}, {{item["title"]}}<br>{{item["teaser"]}}</td>
  <td width="0%">&nbsp;</td>
</tr>
{% endfor %}

呈现模板的Python代码(已通过Python 3.5.6,Jinja2 2.10测试):

import jinja2

# For illustration: list of dict
top_posts = [
    {'date': '06 Jun, 11:40AM', 'title': 'Title 1 goes here',  'teaser': 'One blah blah blah...'},
    {'date': '05 Jun, 04:50PM', 'title': 'Title 2 goes here',  'teaser': 'Two blah blah blah...'},
    {'date': '05 Jun, 09:60AM', 'title': 'Title 3 goes here',  'teaser': 'Three blah blah blah...'}
]

loader = jinja2.FileSystemLoader(searchpath="./")
jenv = jinja2.Environment(loader=loader)
template = jenv.get_template('top.reddit.html')
htmlout = template.render(data=top_posts)
print(htmlout)