---
slug: "DjangoTemplateViewを、@cached_propertyを多用して書いてみる"
title: "Django TemplateView を、@cached_property を多用して書いてみる"
description: "\n\n\nDjango に標準搭載の django.views.generic.TemplateView。"
url: "https://www.ytyng.com/blog/DjangoTemplateViewを、@cached_propertyを多用して書いてみる"
publish_date: "2015-10-29T08:35:23Z"
created: "2015-10-29T08:35:23Z"
updated: "2026-02-27T10:43:09.233Z"
categories: ["Django"]
keywords: ""
featured_image_url: "https://media.ytyng.com/resize/20230812/1d62e61764ce49089fa1ac574246d770.png.webp?width=768"
has_video: false
has_music: false
video_urls: []
music_urls: []
lang: "ja"
---

# Django TemplateView を、@cached_property を多用して書いてみる

<div class="document">


<p>Django に標準搭載の django.views.generic.TemplateView。</p>
<p>HTML生成に必要なメソッドが全部入りで、非常に簡単にページを作ることができます。</p>
<p>シンプルながら機能が豊富で柔軟なため、いろんな書き方ができます。</p>
<p>・get メソッドをオーバーライドする</p>
<pre class="literal-block">def get(self, request, **kwargs):
    return self.render_to_response({
            'items': Hoge.objects.filter(...)
        })
</pre>
<p>・urls.py から変数を差し込む</p>
<pre class="literal-block">url(r'^page/$',
    TemplateView.as_view(
        template_name="html_page/agreement.html",
        items=xxx),
    name='page'),
</pre>
<p>今回は、cached_property 主体でテンプレートに変数を送る例です。</p>
<p>TemplateView の、get を見てみると、</p>
<pre class="literal-block">context = self.get_context_data(**kwargs)
</pre>
<p>というコードがあります。そして、 get_context_data を見てみると</p>
<pre class="literal-block">def get_context_data(self, **kwargs):
    if 'view' not in kwargs:
        kwargs['view'] = self
    return kwargs
</pre>
<p>となっています。</p>
<p>つまり、TemplateView の get, および get_context_data をオーバーライドしない場合、テンプレート内から view という引数で、呼び出し元の ビューインスタンスにアクセスできます。</p>
<p>そのため</p>
<pre class="literal-block">class HogeView(TemplateView):
    template_name = '........'

    @cached_property
    def items(self):
        return list(Hoge.objects.filter(...))

    @cached_property
    def total(self):
        return sum([ i.count for i in self.items])

    @cached_property
    def average(self):
        return self.total / len(self.items)
</pre>
<p>テンプレート</p>
<pre class="literal-block">&lt;table&gt;
{% for item in view.items %}
  &lt;tr&gt; .... {{ item.... }} &lt;/tr&gt;
{% endfor %}
&lt;/table&gt;

合計: {{ view.total }}

平均: {{ view.average }}
</pre>
<p>このような書き方もアリかなと。興味の分離ができて、発行する SQL も少なくできます。</p>
<p>ただし、例外が出た時に握りつぶされてしまうという欠点があります。</p>
</div>
