Djangoのtemplateでちょっとしたifを省略する場合の話です。Listを元にDOMノードを作成しているときに、元データに応じてCSSクラスを変更したい場合の話です。以下のようなケースをもう少しきれいに書きたくなったので調べました。
<ul> {% for row in data_list %} {% if row.is_active %} <li class="active"> <!-- is_activeの場合にactivteクラスを付与したい--> {% else %} <li class=""> {% endif %} {{ row.value }} </li> {% endfor %} </ul>
上のコードの問題
templateであまりに複雑なコードを書いてしまうのは、ロジックの分離という点で望ましくありません。また上のコードは例えば以下のようなactive以外に共通のクラスがあるケースで冗長なコードが生じます。
<ul> {% for row in data_list %} {% if row.is_active %} <li class="row active"> {% else %} <li class="row"> {% endif %} {{ row.value }} </li> {% endfor %} </ul>
row
が2箇所にあり冗長です。またis_active
以外の条件分岐が必要になった場合、あっという間に複雑なtemplateが生まれてしまいます。
これを回避するにはyesnoフィルター
が便利です。
yesnoフィルター
yesnoフィルター
は以下のように利用します。
{{ value|yesno:'trueの場合の値, falseの場合の値'}}
このコードは以下と同義です。
if value: return 'trueの場合の値' else: return 'falseの場合の値'
今回はis_active=True
のときだけactive
クラスを付与し、そうでない場合はなにもしないので以下のようにカンマの後は何も記載しなければ良いです。(,は必要です)
<ul> {% for row in data_list %} <li class="row {{ row.is_active|yesno:'active,'}}"> <!-- is_activeの場合にactivteクラスを付与--> {{ row.value }} </li> {% endfor %} </ul>
if
を使った場合と比べるとかなりスッキリしました。この書き方であればis_admin
といった属性が増えたとしても以下のようにシンプルなママ書くことができます。
<ul> {% for row in data_list %} <li class=" row {{ row.is_active|yesno:'active,'}} {{ row.is_admin|yesno:'admin,normal'}} "> {{ row.value }} </li> {% endfor %} </ul>
template部分はできるだけシンプルに保ちたいので今回のようなケースではyesnoフィルター
は便利でいいですね。