今回のテーマは「TemplateViewでテンプレートを表示する」です。テンプレートを表示するためにはViewに書いた関数でrenderを使えば良いことを紹介してきました。ここでもう1つの表示方法を紹介しておきます。 ※本ページは1-6. テンプレートの継承とincludeまで読まれた方を対象としています。そのためサンプルソースコードが省略されている場合があります。
関数のビューとクラスベースビュー
Djangoのビューの書き方は関数で書く場合とクラスベースビューというクラスを用いる方法があります。歴史的には関数によるビューが先で、オブジェクティブな拡張性をもとめてクラスベースのビューが登場したようです。(参考:クラスベースビュー入門)
クラスベースビューには汎用的に用いられるものがDjango側で予め用意してあり、それらのクラスをオーバーライドして拡張して使うことが頻繁にあります。関数型のビューだけでなくクラスベースビューにも早いうちから慣れておくことが良いと思います。
TemplateViewを使ってみる
汎用的なクラスベースビューにはTemplateView, DetailView, ListViewなどがあり、より少ないコードで表示できるよう工夫してあります。今回はTemplateViewを使ってみます。TemplateViewはViewクラスをオーバライドしたテンプレートを表示するためのビュークラスです。現在のbase/views.pyを書き換えてみましょう。
base/views.py
from django.views.generic import TemplateView
class TopView(TemplateView):
template_name = 'base/top.html'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['title'] = 'IT学習ちゃんねる(仮)'
return ctx
base/urls.pyも作成したTopViewを使用するように書き換えます。
base/urls.py(一部抜粋)
urlpatterns = [
- path('', views.top, name='top'
+ path('', views.TopView.as_view(), name='top'),
]
これだけでは何のメリットがあるのか分からないかも知れませんが、クラスベースビューは頻繁に使いますので覚えておいて損はないです。また、テンプレートにコンテキストを渡す際に、get_context_data関数をオーバーライドする方法もよく用います。(この他にも方法はあるのですが、今はこの方法だけ覚えておけばよいかと思います。) TemplateViewのもう少し便利な使い方を見ていきましょう。もしコンテキストをviews.pyから渡す必要がない場合はurls.pyのみで完結することも出来ます。単順にHMTLファイルを出力したいだけの場合はviews.pyからコンテキストを渡す必要はありません。今回は利用規約ページがそのようなページに相当する想定で実装してみます。 まずはテンプレートを用意します。
templates/base/terms.html
{% extends 'base/base.html' %}
{% block title %}利用規約 - {{ block.super }}{% endblock %}
{% block content %}
<div class="ui grid stackable">
<div class="eleven wide column">
<div class="ui breadcrumb">
<a href="{% url 'base:top' %}" class="section">TOP</a>
<i class="right angle icon divider"></i>
<a class="active section">利用規約</a>
</div>
<div class="ui segment">
<div class="content">
<div class="header"><h3>利用規約</h3></div>
<p>あんなことやこんなことを守って下さい。などなど</p>
<p>...............</p>
<p>...........</p>
<p>.......</p>
</div>
</div>
</div>
{% include 'base/sidebar.html' %}
</div>
{% endblock %}
base/urls.pyは以下のように変更します。
base/urls.py
from django.urls import path
+ from django.views.generic import TemplateView
from . import views
app_name = 'base'
urlpatterns = [
path('', views.top, name='top'),
+ path('terms/', TemplateView.as_view(template_name='base/terms.html'), name='terms'),
]
ブラウザで確認すると以下のようになります。
ここでbase/terms.htmlの中でリンク先の指定時に{% url ‘base:top’ %}を用いました。このように書くとbase/urls.pyでapp_nameで指定した’base’アプリケーション名の’top’のURLを自動的に挿入してくれます。便利なのでよく使います。また、views.pyの中でもリダイレクト時などに良く出てくる表現です。さて、本題ですが、これでテンプレートを表示するだけであればurls.pyだけで事足りることが分かりましたね。
最後に
TemplateViewの使い方いかがだったでしょうか?歴史的な経緯もあり、テンプレートを表示するだけでも色々な方法があります。最初は戸惑うかも知れませんが、だんだんと慣れていくと自分の好みの方法が見つかると思います。ここまでとても簡単ですがビューとテンプレートを扱ってきました。次回はMVTのMであるモデルを扱っていきます。
Sponsored Link
class TopView(TemplateView):
NameError: name ‘TemplateView’ is not defined
とですのでこちらはviewクラスをインポートしないといけないのでしょうか?
MKさん
コメントありがとうございます。ご指摘の通りTemplateViewのインポートが必要です。コードの抜粋時に漏れがあり失礼しました。修正しておきます。
もう一つですがファイル名がtemplates/base/terms.pyなのですが
こちらはテンプレートなので正しくはterms.htmlでしょうか?
こちらもご指摘の通りterms.htmlが正です。
ご連絡いただきありがとうございました!
おそらくbase.html が前回(1-6)から変わっているような気がします。
MOTOさん
1-7ではbase.htmlのコードを示していないので、1-6から「変わっている」というのが理解できないのですが、どういうことでしょうか?「ような気がする」では話が遠いので具体的に指摘箇所を教えて頂けると助かります。
本稿の意図としてはterms.htmlにおいてbase.htmlの拡張を用いて作成し、それをTemplateViewクラスを用いて表示してみるということでありbase.htmlに関しては1-6で使用したものをそのまま使用するつもりで書いています。
返信ありがとうございます。
『ブラウザで確認すると以下のようになります。』
の下ではトピックの作成というaタグのようなものがありますが、
これはこれまでのbase.htmlで出力されますでしょうか?
私は利用規約のurlに飛べずに詰まってしまって…、base.thmlの問題ではなく、私の問題でしたらすいません。
MOTOさん
ご指摘の意味が理解できました。画像の内容とソースコードが一致していないということですね。些細なHTMLの差異は本質的な部分ではないと思い本稿より後で実装する内容の画像を載せてしまいました。混乱を招いてしまい申し訳ありません。画像を差し替えました。
コメント失礼いたします。毎回とても分かりやすい解説でdjangoの学習に大変重宝しております。
質問なのですが、terms.htmlをブラウザに突っ込むと、
{% extends ‘base/base.html’ %} {% block title %} 利用規約 – {{ block.super }} {% endblock %} {% block content %}
TOP 利用規約
利用規約
あんなことやこんなことを守って下さい。などなど
……………
………..
…….
{% include “base/sidebar.html” %}
{% endblock %}
と表示されてしまい、base.htmlの継承がうまくいきません。sidebar.htmlやtop.htmlでも同様の現象が起きてしまいます。base.htmlはtemplates/base内に置いてあります。解決策をご存じでしたらご教授ください。