知識の枝

"All is well"

クラスベースビューで複数の変数をテンプレートに渡す

約217日前 2021年4月24日9:56
デジタル
Django

改訂履歴


2021/4/24 投稿

1. 背景


Djangoを使った開発中に覚えたことを備忘録として残します。

今回はクラスベースで書かれたviewからテンプレートに複数の変数を渡す方法を解説します。


2. ゴール


複数用意した変数をhtmlテンプレートに渡し、html上で表示する。


3. 変数を渡す


3.1 - 1つだけ渡す場合


関数ベースで書く場合は こちらの記事 を参考にして下さい。


まず、クラスベースビューの書き方です。
クラスベースビューのうち汎用ビューの1つ「ListView」を例にとります。
views.py
class PostListView(ListView):
"""記事の一覧表示"""
model = Post
template_name = 'post_lists.html'
記事の一覧表示を簡単に実装可能な「ListView」では、一覧表示したいモデルを「model = ●●」というように設定します。

「template_name = '●●'」で開くhtmlファイルを設定します。

関数ベースの書き方ではhtmlテンプレートに渡す変数を辞書形式で指定していましたが、上記には辞書がありません。
関数ベースの場合
def postlistview(request):

context = {
'posts': Post, #辞書で指定
}

return render(request, 'post_list.html', context)



ではどのようにして変数をテンプレートに渡しているのでしょうか?
なんとクラスベースビューではDjangoが気を利かせ、自動で変数をhtmlテンプレートに渡してくれています。


テンプレート内での記述方法です。
ListViewの場合はmodelで設定したモデルを全数取得し、object_listという変数名で扱うことができます。
htmlでの記述方法
{% for post in object_list %}
{{ post }}
{% endfor %}
変数リストからfor文で取り出すことができます。


他の例も見てみましょう。
別の汎用ビューである「DetailView」の場合はモデル全数ではなく1件のみ渡す仕様ですので、object_listではなくobjectという変数名で扱うことができます。
htmlでの記述方法
{{ object }}


Djangoが勝手に変数を用意してくれるので、わざわざ指定する手間が省けて便利ですね。
でも、object_listやobjectという変数名だとテンプレートを読んだ際に何のモデルを扱っているのか分かり難いですよね。

実はそのあたりもDjangoが気を利かせてくれています。
「object」の部分をviews.pyで設定したモデル名に置き換えても変数として扱うことができるんです!

Postというモデルを設定している場合は下記のように書き換えても動作します。
{{ object_list }} → {{ post_list }}
{{ object }} → {{ post }}



3.2 - 2つ以上渡す場合


前置きが長くなりましたが、ここからがこの記事の本題。
「複数の変数をテンプレートに渡す方法」です。

先ほどのviews.pyの書き方だと1つのビューで1つのモデルしか設定できない為、テンプレート内でも1つの変数しか扱うことができませんでした。
model = Post   #1つしか設定できない

そんなときに使うのが汎用ビューが持つメソッドの1つ「get_context_data関数」です。

まず例をみてみましょう。
views.py
class PostListView(ListView):
"""記事の一覧表示"""
model = Post
template_name = 'post_lists.html'

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['names'] = Author.objects.all()
return context
これは適当な例ですが、Postというモデルの他にAuthorというモデルをテンプレートに渡しています。

関数の中で
context['変数名'] = 代入したいもの
と記述するだけで、テンプレートに渡す変数を増やすことができます。

もっと増やしたい場合は
context['変数名'] = "ABC"
context['変数名'] = モデル名.objects.all()
context['変数名'] = モデル名.objects.filter(hogehoge).order_by('foo')
というように書き足すだけです。

どんな変数でも追加することができるので、何か別の関数の結果を代入してもいいですし、別のモデルを入れてもいいです。

htmlテンプレート内では context['変数名'] で指定した名前で扱うことができます。
{{ 変数名 }}


複数の変数を渡す方法は以上です。


4. さいごに


この方法が使えるようになると出来ることの幅がグッと広がりそうですね!
私も使いこなせるように精進します!

お疲れ様でした。