SE(たぶん)の雑感記

一応SEやっている筆者の思ったことを書き連ねます。会計学もやってたので、両方を生かした記事を書きたいと考えています。 でもテーマが定まってない感がすごい。

DjangoのTemplateで辞書(dict)の中身を表示する

最近は業務で、Djangoを使って雑なサイトをおためしで作る*1仕事をやっています。

一週間で作るもの決めて、とにかくスピード勝負で見せるという状況です。

最低限のチュートリアルは、一年前に実施しています。

hiroronn.hatenablog.jp

ところで、Djangoチュートリアルを見ると、たいていは

  • ModelでDBとのマッピングを作成
  • ViewModelからデータを取得し、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インスタンスではないlistdictインスタンスを渡します。

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で使う場合も一緒で良いようです。

こんな感じで表示されます。

f:id:hiroronn:20181010085853p:plain

おわりに

この調子だと、独自クラスであっても、表示可能なような気がします。

標準テンプレート*3を使う場合より生産性は落ちますが、独自クラスを使えるなら実装の選択肢が広がりそうです。

もっと使い慣れたら、いろいろ試していきます。

今回はあっさりな記事でした。

*1:サイトを作ることが目的ではなく、ファイルからDBに値を入れてブラウザで確認するのが目的

*2:いわゆるMVCとは、Viewの役割が違う。DjangoのViewは、MVCのcontrollerに近い

*3:ListView, DetailView等