【问题标题】:Rendering a dictionary in Jinja2在 Jinja2 中渲染字典
【发布时间】:2013-10-09 01:58:00
【问题描述】:

我正在使用网址缩短器(基于 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 %}

问题是,我似乎无法访问字典中的项目。

线

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

是我关注的地方。如上所述,我得到了字典中的键列表。

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

什么都不返回。没有任何一个 {{ user.url }}">{{ user.username }} 在文档中输入内容似乎有效。

请出主意?新手——温柔点。谢谢。

更新

感谢您的回复。

Ewan 的答案有效,但使用了一个字典列表。我想传递一个字典并渲染它(因为我想要一个非整数索引项)。 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' 没有属性 'iteritems'

再次感谢。

仍然对为什么它认为我正在传递一个列表但现在可以正常工作感到困惑。

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

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

【问题讨论】:

  • 在我看来这不像是字典...这是一个以字典为第二个元素的元组列表。

标签: python jinja2


【解决方案1】:

您的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 %}

【讨论】:

  • 在 Python 3 中,您的 url_list.iteritems 将是 url_list.items()(并且您需要括号来调用它)。
  • @Noumenon - 好点,有趣的是社区编辑删除了括号,但我将重新添加并包含一个 python 3 示例。感谢您指出这一点。
  • 谢谢!这对我帮助很大!
【解决方案2】:

一种方法是将处理逻辑与 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)

【讨论】:

    【解决方案3】:

    请注意,dict.items() 方法在 Python 2 和 Python 3 中都存在。但该方法不保证字典中包含的订单项正在迭代。这就是为什么此示例使用字典列表而不是您上面所说的字典字典更有意义的原因。

    【讨论】:

      猜你喜欢
      • 2015-05-05
      • 2019-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多