🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2184閲覧

Djangoにおけるtemplateでの変数参照時に、forloop.counterを使いたい

Test_ks

総合スコア33

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/01/06 07:05

編集2020/01/07 02:09

■Viewで以下のように定義しております。

python

1 hoge ={ 2 'fir':["1","2"], 3 'sec':[["1111","1112"],["2111","2112"]], 4 'third': [[['1111-1','1111-2'],['1112-1','1112-2']], [['2111-1','2111-2'], ['2112-1','2112-2']]] 5 }

template側で現在は、下記のように記述しております。

html

1{% for i in fir %} 2 <h1>{{i}}</h1> 3 <p>{{ sec.forloop.counter }}</p> 4{% endfor %}

出力したいイメージは、以下のようなイメージです。

html

1<h1>1</h1> 2<h2>1111</h2> 3<h3>1111-1</h3> 4<h3>1111-2</h3> 5<h2>1112</h2> 6<h3>1112-1</h3> 7<h3>1112-2</h3> 8<h1>2</h1> 9<h2>2111</h2> 10<h3>2111-1</h3> 11<h3>2111-2</h3> 12<h2>2112</h2> 13<h3>2112-1</h3> 14<h3>2112-2</h3> 15

最終的なイメージは以下のように表示點せてたいです。
イメージ説明

Viewでの変数の設定方法がおかしいのか、Template側でのループの方法がおかしいのか、どのように実現したら良いのか分からない状態です。

どなたかご教授いただけますでしょうか?

ご確認よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

azuapricot

2020/01/06 07:49 編集

i.sec でsecの中身取れませんか? あーそう簡単にはいかないんですねーなるほど
Test_ks

2020/01/06 08:19

出力したいイメージを実現できれば良いのですが、Viewで別の形で値を取って来る方が簡単でしょうか? 例えば、hoge = [1,[1111,1112],[[1111-1,1111-2],[1111-1,1111-2]],[2,[2111,2112],[[2111-1,2111-2],[2111-1,2111-2]]]と定義するほうが簡単でしょうか?
guest

回答2

0

ベストアンサー

解説したくない、保守なんて絶対にしたくない、というようなテンプレートになってしまったのでデータ構造を見直すべきです。

html

1{% for f in fir %} 2 {% with fir_index=forloop.counter %} 3 <h1>{{ f }}</h1> 4 {% for s in sec %} 5 {% with sec_index=forloop.counter %} 6 {% if fir_index == sec_index %} 7 {% for s_item in s %} 8 {% with s_inner_index=forloop.counter %} 9 <h2>{{ s_item }}</h2> 10 {% for t in third %} 11 {% with third_index=forloop.counter %} 12 {% if fir_index == third_index %} 13 {% for t_inner in t %} 14 {% with t_inner_index=forloop.counter %} 15 {% if s_inner_index == t_inner_index %} 16 {% for t_item in t_inner %} 17 <h3>{{ t_item }}</h3> 18 {% endfor %} 19 {% endif %} 20 {% endwith %} 21 {% endfor %} 22 {% endif %} 23 {% endwith %} 24 {% endfor %} 25 {% endwith %} 26 {% endfor %} 27 {% endif %} 28 {% endwith %} 29 {% endfor %} 30 {% endwith %} 31{% endfor %}

結果(spaceless)

html

1<h1>1</h1><h2>1111</h2><h3>1111-1</h3><h3>1111-2</h3><h2>1112</h2><h3>1112-1</h3><h3>1112-2</h3><h1>2</h1><h2>2111</h2><h3>2111-1</h3><h3>2111-2</h3><h2>2112</h2><h3>2112-1</h3><h3>2112-2</h3>

追記
https://stackoverflow.com/questions/2415865/iterating-through-two-lists-in-django-templates#answer-14857664
にあるzipフィルタを使って

html

1{% for fs, t in fir|zip:sec|zip:third %} 2 <h1>{{ fs.0 }}</h1> 3 {% for st in fs.1|zip:t %} 4 <h2>{{ st.0 }}</h2> 5 {% for t in st.1 %} 6 <h3>{{ t }}</h3> 7 {% endfor %} 8 {% endfor %} 9{% endfor %}

と短く書けましたが、これも解説したくない、強く保守したくない、と思ってしまったので、やはりデータ構造を見直すべきです。


追記

python

1@register.filter(name='get') 2def get_attr(a, b): 3 return a[b] 4

というカスタムフィルタを定義すると

html

1{% for f in fir %} 2 {% with fir_index=forloop.counter0 %} 3 <h1>{{ f }}</h1> 4 {% for s in sec|get:fir_index %} 5 {% with sec_index=forloop.counter0 %} 6 <h2>{{ s }}</h2> 7 {% for t in third|get:fir_index|get:sec_index %} 8 <h3>{{ t }}</h3> 9 {% endfor %} 10 {% endwith %} 11 {% endfor %} 12 {% endwith %} 13{% endfor %}

となりました。これなら後から理解できそう。


質問に書いてあるような、無味乾燥で意味を含まないデータからは判断できない、というのが正直なところです。

単純には

pyhton

1 hoge = { 2 'arr': [ 3 [ 4 "1", 5 [ 6 ["1111", ['1111-1', '1111-2']], 7 ["1112", ['1112-1', '1112-2']] 8 ] 9 ], 10 [ 11 "2", 12 [ 13 ["2111", ['2111-1', '2111-2']], 14 ["2112", ['2112-1', '2112-2']] 15 ] 16 ] 17 ], 18 }

となっていれば

html

1{% for f, st in arr %} 2 <h1>{{ f }}</h1> 3 {% for s, t in st %} 4 <h2>{{ s }}</h2> 5 {% for t_item in t %} 6 <h3>{{ t_item }}</h3> 7 {% endfor %} 8 {% endfor %} 9{% endfor %}

と書けるでしょうし、

python

1 hoge = { 2 'dic': { 3 "1": 4 { 5 "1111": ['1111-1', '1111-2'], 6 "1112": ['1112-1', '1112-2'], 7 }, 8 "2": 9 { 10 "2111": ['2111-1', '2111-2'], 11 "2112": ['2112-1', '2112-2'], 12 } 13 } 14 }

となっていれば

html

1{% for f, st in dic.items %} 2 <h1>{{ f }}</h1> 3 {% for s, t in st.items %} 4 <h2>{{ s }}</h2> 5 {% for t_item in t %} 6 <h3>{{ t_item }}</h3> 7 {% endfor %} 8 {% endfor %} 9{% endfor %}

と書けるでしょう。

後者で、辞書のキーになる部分に重複があり得るならこのようには書けないです。また、古いPythonを考慮するならOrderedDictを使うべきです。

テンプレート側の書きやすさと見やすさ、Pythonコード側の書きやすさと見やすさのバランスを取っていく必要があるので、表示しようとしているデータの中身がどう作られるのかも明らかでないと判断しにくいですね。

投稿2020/01/07 00:40

編集2020/01/07 01:36
quickquip

総合スコア11231

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Test_ks

2020/01/07 01:03

ありがとうございます! どのようなデータ構造が望ましいと思いますでしょうか?
Test_ks

2020/01/07 02:12

ありがとうございます。 最終イメージを追記してみました。 最終イメージにするために、テンプレート側で、ループの初回だけ、 <td> へrowspanを設定する必要があるので、そこが少し大変ですかね、、、
guest

0

動作確認してないですけどこんな感じでできませんかね

HTML

1{% for count in hoge.fir %} 2{% with forloop.counter as outer_counter %} 3 <h1>{{count}}</h1> 4 5 {% for seccount in hoge.sec.outer_counter %} 6 {% with forloop.counter as inner_counter %} 7 <p>{{ seccount }}</p> 8 9 {% for thirdcount in hoge.third.outer_counter.innner_counter %} 10 <p>{{ thirdcount }}</p> 11 {% endfor %} 12 {% endwith %} 13 {% endfor %} 14{% endwith %} 15{% endfor %}

投稿2020/01/06 08:05

azuapricot

総合スコア2341

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Test_ks

2020/01/06 08:14

ご確認ありがとうございます。 下記の部分のみ有効で、それ以外は表示されません。。。 <h1>{{count}}</h1>
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問