DjangoのTemplateで辞書(dict)の中身を表示する
最近は業務で、Djangoを使って雑なサイトをおためしで作る*1仕事をやっています。
一週間で作るもの決めて、とにかくスピード勝負で見せるという状況です。
最低限のチュートリアルは、一年前に実施しています。
ところで、Djangoのチュートリアルを見ると、たいていは
ModelでDBとのマッピングを作成ViewでModelからデータを取得し、Templateに渡すTemplateでそのデータを表示する
のようになっています*2。
しかし、DBの構造とは異なる形でデータを表示したい場合に、どうやってやるの?という疑問が湧きました。
ある程度正規化されたデータを崩す場合も含みます。
そこで、わりと分かりやすい辞書(dict)を表示できるか、試しました。
要するに、ASP.NET MVCでいうところのViewModelが欲しいんです。
バージョン
| 種類 | バージョン |
|---|---|
| Python | 3.7.0 |
| Django | 2.1.1 |
View定義
今回、Modelは登場しません。
- Views.py
class HomeView(TemplateView): template_name = "home.html" def get(self, request, *args, **kwargs): context = super(HomeView, self).get_context_data(**kwargs) context['direct'] = ["apple", "orange", "banana"] context['direct_dict'] = { "name": "fruits", "kinds": {"apple": 2, "orange": 3, "banana": 4}} return render(self.request, self.template_name, context)
contextに、Modelのインスタンスではないlistとdictのインスタンスを渡します。
dictは、辞書の中に辞書を持つ、いわゆるネストした形で持たせます。
- template/home.html
よくあるやつですが、base.htmlから継承し、bodyだけ書けるようにしています。
{% extends "base.html" %}
{% block body %}
{% for f in direct %}
<ul>
<li>{{ f }}</li>
</ul>
{% endfor %}
<ul>
<li>{{ direct_dict.name }}</li>
{% for key, value in direct_dict.kinds.items %}
<ul>
<li>{{ key }} - {{ value }}</li>
</ul>
{% endfor %}
</ul>
{% endblock %}
listの表示
{% for f in direct %}
<ul>
<li>{{ f }}</li>
</ul>
{% endfor %}
Viewから渡したdirectの中身を、単にループして取り出して表示できます。
dictの表示
二つの方法があるようです。
- キー名を指定して表示
<li>{{ direct_dict.name }}</li>
上記のように、変数名.キー名とすると、そのキーの値を表示できます。
- キーと値を列挙
{% for key, value in direct_dict.kinds.items %}
<ul>
<li>{{ key }} - {{ value }}</li>
</ul>
{% endfor %}
ネストしている辞書の中身を、ループで表示します。
Pythonで辞書の中身を列挙する場合、
for k, v in direct_dict.items(): print('key = %s, value = %s' % (k, v))
のように、itemsを使う(ここに記載がある)こととなっています。
なんと、Templateで使う場合も一緒で良いようです。
こんな感じで表示されます。

おわりに
この調子だと、独自クラスであっても、表示可能なような気がします。
標準テンプレート*3を使う場合より生産性は落ちますが、独自クラスを使えるなら実装の選択肢が広がりそうです。
もっと使い慣れたら、いろいろ試していきます。
今回はあっさりな記事でした。