【Django】TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()

【Django】TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()

こんなエラーが出てきたので翻訳機に掛けてみました。

TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()

TemplateResponseMixin は 'template_name' の定義か 'get_template_names() の実装を必要とします。
(意訳)TemplateResponseMixinと言う所にデータが渡ってきたけど必要な情報揃ってないよ。

今回解決に至った方法

Views.py で継承しているクラスを確認し適切なものに変更

まぁね、まだまだな訳です。
Django初心者、参考図書のルート上にある事はやりたい様に動かせても、テキストのルートを少し外れると不明な事ばかりです。今回はそんな問題の一端でした。

#views.py

import logging
from django.urls import reverse_lazy
from django.contrib import messages
from django.views import generic
from django.shortcuts import render
from .models import Company
from .forms import InquiryForm,

logger = logging.getLogger(__name__)

class IndexView(generic.TemplateView):
    template_name = "websites/index.html"


class InquiryView(generic.FormView):
    template_name = "websites/inquiry.html"
    form_class = InquiryForm
    success_url = reverse_lazy('company:inquiry')

    def form_valid(self, form):
        form.send_email()
        messages.success(self.request, 'メッセージを送信しました。')
        logger.info('Inquiry sent by {}'.format(form.cleaned_data['name']))
        return super().form_valid(form)

class ServiceView(generic.FormView):
    template_name = "websites/service.html"

この中の28行目【class ServiceView(generic.FormView):】を【class ServiceView(generic.FormView):】と修正するとエラーの発生はなくなります。

class ServiceView(generic.TemplateView):
    template_name = "websites/service.html"

この方法だと website/service.htmlに記載した値をurl.pyで関連付けたアドレスで表記してくれます。

#urls.py
from django.urls import path
from . import views

app_name = 'web'
urlpatterns = [
  path('', views.IndexView.as_view(), name="index"),
  path('inquiry', views.InquiryView.as_view(), name="inquiry"),
  path('service', views.ServiceView.as_view(), name="service"),

こんな感じでurls.pyを書いていれば、https://ドメイン/service にアクセスすれば websites/service.html を表示します。でもやりたのはそこじゃないんです。

FormView と書いてみたのはDBに格納した値を表示したかったからなんですよね。

WordPressのようにSQLにHTMLを格納しページに表示するための構成

今回はSQLに【 contents 】というテーブルを用意し次のようなフィールドを用意しました。

  • types:記載ページを指示(informationかserviceかといったフラグ)
  • name:記載内容(contents)のタイトル。WEBに表現する時はhタグをつけて飾る予定
  • contents:記載するHTMLを格納する場所。bootstrapのルールに従っておけばテンプレート変更で色々変更出来るはず。
  • sort_number:typesの中の並び替え。コンテンツを小分けにした方が融通を利かせられるので用意。
  • switch:WEBへの表示対象とするかを表すマーカー。Falseにしておけば表示しないのでWEBサイトの変更に活用できる。

これをmodels.pyに表現するとこんな感じ。

#models.py
from django.db import models
from django.core.validators import RegexValidator

class Contents(models.Model):
    """CMS_WEB記載内容/要素"""
    CATEGORY_CHOICES = (
        (1, 'インフォ'),
        (2, 'サービス'),
        (3, 'プロジェクト'),
        (4, 'プロフィール'),
    )
    types = models.IntegerField(verbose_name='記載箇所', choices=CATEGORY_CHOICES)
    name = models.CharField(verbose_name="コンテンツ名", max_length=100, blank=False, null=True)
    contents = models.TextField(verbose_name="HTMLコード", blank=False, null=True)
    sort_number = models.IntegerField(verbose_name='並び順', blank=False, default=1)
    switch = models.BooleanField(verbose_name='ON/OFF', blank=False, default=True)
    created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)

    class Meta:
        verbose_name_plural = 'Contents'

        def __str__(self):
            return self.name

この状態でマイグレーションを実行すれば設定したSQLサーバーにテーブルを作成してくれます。
Djangoではこうしてmodels.Model に紐づけたテーブル構成はQuerySetとして扱う事が出来る様です。
で、Views.pyではこのQuerySetを呼出して欲しい値の抽出を行います。

#views.py
(前略)

def ServiceView(request):
    data = Contents.objects.filter(switch=1).filter(types=2).order_by('sort_number')
    params = {
        'title': '事業内容',
        'data': data
    }
    return render(request, 'websites/service.html', params)

この時のurls.pyは下のようにします。

#urls.py
(前略)
urlpatterns = [
  (中略)
  path('service', views.ServiceView, name="service"),
]

これで、https://ドメイン/service にアクセスしてきた場合 contentsテーブルの値にフィルターかけて抽出したものをservice.htmlに渡して表示する事が出来ます。

CMSの原型がこれで完成です。

まとめ

ここまででなかなか手こずったのは【class】と【def】の違いと記載方法でした。

Laravelを道具にしてた私からすると【def】の書き出しになじみがなく、全てClassで書いていたのですが[ class ServiceView(request): ] とするとエラーなんですよね。classではrequestを呼び込めないのか、動線が異なるのか、ここら辺はまだ「理解してる」と言い難いです。

まぁ作りながら理解してくしかないですね。
今日も頑張りましょう!

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。