[Django]知ってると便利なforで使える小技
Djangoのtemplate内で利用するfor文
で知ってるとテンプレートがすっきり書けるかもしれない小技の紹介
まずはシンプルに
"values":["A","B","C"]
{% for value in values %}
{{ value }}
{% endfor %}
シンプルにリストをforで回しました。
タプルやレンジオブジェクトも同様に回すことが可能です。
辞書のkeyとvalueを同時に
"dic":{"A":"APPLE","B":"BANANA","C":"CHERRY"}
{% for k,v in dic.items %}
<p>{{ k }}{{ v }}</p>
{% endfor %}
変数を二つ用意してforを回します。
ここまでは普通のPythonとそう変わりはありません。
リストの中身がないときに別の内容を表示
{% for value in values %}
<p>{{ value }}</p>
{% empty %}
<p>the list is empty.</p>
{% endfor %}
{% empty %}
節を加えることでリストの中身が空だった場合に別の内容を表示できます。
上の場合リストの中身が空であれば<p>the list is empty.</p>
が表示されます。
以下のように書いても同じことはできますが、{% empty %}
節のほうが見やすいうえに意味も分かりやすいので積極的に上の方法を利用しましょう。
{% if values %}
{% for value in values %}
<p>{{ value }}</p>
{% endfor %}
{% else %}
<p>the list is empty.</p>
{% endif %}
リストのうちの一部を表示
{% for value in values | slice:"2:5"%}
<p>{{ value }}</p>
sliceフィルタを用いることで、リストの一部を表示することができます。
上の場合はリストの二番目から四番目までが表示されます。
sliceフィルタの引数を":5"
とすれば最初から四番目まで、"2:"
とすれば二番目から最後までが表示されます。
ループの最初だけ別の処理を行う
{% for value in values %}
{% if forloop.first %}
<p>This is first time. {{ value }}</p>
{% else %}
<p>{{ value }}</p>
{% endif %}
{% endfor %}
forループの中でforloop.first
を用いると一回目のループの時にTrue
、それ以外の時にFalse
を返します。
if文と組みあわせるとループの最初だけ別の処理をさせることができます。
ループの最後だけ別の処理を行う
{% for value in values %}
{% if forloop.last %}
<p>This is last time. {{ value }}</p>
{% else %}
<p>{{ value }}</p>
{% endif %}
{% endfor %}
forloop.last
はループの最後の時にTrue
、それ以外の時にFalse
を返してくれます。
こちらも、if文と組みあわせるとループの最後だけ別の処理をさせることができます。
forloop.first
とforloop.last
は同時に使うこともできます。
ループカウントを取得する
{% for value in values %}
<p>index:{{ forloop.counter0 }}/
count:{{ forloop.counter }}/
value:{{ value }}</p>
{% endfor %}
forloop.counter
はループの回数を1からカウントアップします。
一回目のループなら1
、二回目のループなら2
、N回目ならN
になります。
forloop.counter0
はループの回数を0からカウントアップします。
一回目のループなら0
、二回目のループなら1
、N回目ならN-1
になります。
ちょうどPythonの組み込み関数のenumerate
と同じです。
ループカウントを逆順で取得する
{% for value in values %}
<p>index:{{ forloop.revcounter0 }}/
count:{{ forloop.revcounter }}/
value:{{ value }}</p>
{% endfor %}
forloop.revcounter
はループの回数をNからカウントダウンします。
一回目のループならN
、二回目のループならN-1
、N回目なら1
になります。
forloop.revcounter0
はループの回数をN-1からカウントダウンします。
一回目のループならN-1
、二回目のループならN-2
、N回目なら0
になります。
それぞれ、forloop.counter
、forloop.counter0
の逆です。
おまけ
勘のいいひとは気づいたかもしれませんが、forloop.counter
とif文を組み合わせるとループの特定の回数のところで別の処理をする、といったことが実現できます。
{% for value in values %}
{%if forloop.counter|divisibleby:"3" %}
<p>this is a multiple of three. {{ forloop.counter }}</p>
{% else %}
<p>{{ value }}</p>
{% endif %}
{% endfor %}
divisibleby
フィルターと組み合わせれば一定回数ごとに別の処理をするといったこともできます。
上記の例では三回ごとに違う処理をしています。
divisiblebyフィルター 値が引数の値で割り切れる場合に True を返します。
最後に
今回紹介した小技を駆使することでtemplateをすっきり書けるかもしれません。
一度自分の書いたtemplateを見直してみるのもいいかもしれません。
viewとtemplateを分離して書くことができるので、筆者はかなりすっきり書けるようになりました。(viewのほうが)