Jinja: 「items」要素を持つオブジェクトを反復処理することはできません

作成日 2017年01月09日  ·  10コメント  ·  ソース: pallets/jinja

サーバーはこのJSONを返しています:
{{
「アイテム」:[1,2,3]
..。
}

'items'を反復しようとすると、次のようになります。
{data.items%のelの%}
...。
TypeError: 'builtin_function_or_method'オブジェクトは反復可能ではありません

上記は、Python dictに組み込み関数「items()」があるために発生します。

臨時雇用者として。 回避策として、フックをインストールし、JSON応答のキーの名前を「items」から「__items」に変更してから、それをJinja2に渡しました。 その時点で、名前が変更された属性を繰り返し処理しています。
{%for el in data .__ items%}

理想的には、Jinja2は、function()表記で特に呼び出されない限り、forループまたはifステートメントの組み込み関数を無視する必要があります。

最も参考になるコメント

{% for el in data['items'] %}を使用して、アイテムに優先順位を付けることができます。 これはドキュメントでも説明されています。 http://jinja.pocoo.org/docs/2.9/templates/#variables

全てのコメント10件

{% for el in data['items'] %}を使用して、アイテムに優先順位を付けることができます。 これはドキュメントでも説明されています。 http://jinja.pocoo.org/docs/2.9/templates/#variables

JSON応答に「items」が含まれていない場合は失敗します(応答のオプションの属性であると言います)。 その場合、{%for el in data ['items']%}も次を生成します。
TypeError: 'builtin_function_or_method'オブジェクトは反復可能ではありません

...アイテムは常に定義されているため(組み込み関数として)。

そしてこれはバグです、IMO。 data ['items']はビルトインと衝突してはいけません。 つまり、オプションの「items」属性をきれいに繰り返したい場合は、名前を変更する必要があります。 理想的には、そうではないはずです。

JSON応答にアイテムが含まれないのはなぜですか? ここで問題が発生するかどうかは完全にはわかりません。 確かにあなたはあなたのデータが何であるかを前もって知っています。 テンプレートで、辞書のin演算子を使用してキーを確認することもできます。

この属性/アイテムのサポートを削除すると、何千ものテンプレートが壊れてしまうため、この動作を変更することはまったく問題外です。

厳密にするためだけに、何かを削除することは提案していません。

今日の問題は、明示的なルックアップ表記を使用すると、 data['items']が組み込みの辞書関数検出し、検出しdata.items()

そこで特別な場合のdict.itemsが非常に明確であるかどうかはわかりません。 特に、カスタムdictのような型、あるいはOrderedDictでも失敗するためです。 そのような場合はfoo['items']の方が良いと思います。 それは超きれいではありませんが、一貫した動作です。

唯一の可能な「修正/ハック」私はよりよいの方法でこれをhancleするために想像できるが、プレーン属性(すなわちない関数呼び出しは)反復で使用されいて、反復可能しかし呼び出すことはできません何かを反復処理しようとしているかどうかをチェックしています。 この場合、アイテムを試してみても、既存のコードが破損する可能性はほとんどありません。 ただし、Jinjaでのこのような動作の実装は、おそらく非常にひどいものになるでしょう;)

なぜこれが特別な場合なのですか? JinjaがPythonとまったく同じように動作するようにお願いしています。 具体的には、ユーザーが挿入したキー「items」が含まれていない場合、foo ['items']はNoneを生成する必要があります。 今日、Jinjaは同じ名前の組み込み関数を見つけることにフォールバックします。 したがって、Pythonが行うことを単純に実行します。

>>> print {}.get('items')
None

ところで、呼び出し可能オブジェクトを呼び出すには「()」を使用する必要があるため、代替表記「foo.items」も問題なく処理されるはずですが、foo.itemsの下位互換性が必要な場合はキーを押すか、関数を自動的に呼び出すと、それは残念だと思います。

['x']と.x両方のJinjaロジックは次のとおりです。

  • item / attr(Pythonで取得する構文が何であれ)が存在するかどうかを確認し、存在する場合はそれを使用します
  • attr / item(Pythonで構文が行うことの「反対」)が存在するかどうかを確認します。存在する場合は、それを使用します。
  • どちらも存在しない場合は失敗します

したがって、 x.itemsは属性をチェックし、属性が存在するため、それを使用します。 このロジックは、コンテストに関係なくこのように機能します。 これを改善するには、コンテキストに応じて属性ルックアップロジックを変更する必要があります。 そしてそれでも、このコードのような厄介な状況が機能する結果になります。

{% for x in mydict.items %}

対このコードは機能しません

{% set items = mydict.items %}
{% for x in items %}

そして、この場合の特別な処理を維持することは、変数がどこから来たのかを追跡しなければ、単純に不可能です。

@slisznia基本的に、この時点で約7年間導入されている属性ルックアップシステムを完全に変更するように

ああ、 foo['bar']属性ルックアップを行わないという提案すら見ませんでした。 それは確かに悪い考えです! for item in data.get('items', [])を使用するだけで何が問題になりますか?

@ThiefMaster mydict.get('items', [])はもちろん機能します。キーの名前を変更する以外の方法を指摘していただき、ありがとうございます。

このページは役に立ちましたか?
0 / 5 - 0 評価