web-dev-qa-db-ja.com

Jinja2 / Werkzeugでpython dictをレンダリングする

URL短縮サービスで遊んでいます(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>

私が注目しているところです。上記のように、dictのキーのリストを取得します。

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

何も返しません。ドキュメント内の{{user.url}} "> {{user.username}}タイプのものはどれも機能していないようです。

アイデアください?初心者-優しくしてください。ありがとう。

更新

回答ありがとうございます。

ユアンの答えは機能しますが、辞書のリストを使用します。 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'}}

さらに実験-辞書を渡すと、リストオブジェクトに関するエラーが生成されます。

   {% 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>

すべてを印刷します。どうもありがとう。

22
user2839288

きみの 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

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

dict.items()メソッドはPython 2とPython 3.の両方に存在することに注意してください。上記のような辞書の辞書の代わりに辞書のリストを使用することは、この例がより理にかなっている理由です。

0
Federico Ressi

1つのアプローチは、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)
0
coder.in.me