Djangoのviewには2つの種類があります。
・ファンクションベースビュー
・クラスベースビュー
両者の違いは、Viewを、関数型プログラミングで記述するか、オブジェクト指向(クラス)で記述するかの違いです。
オブジェクト指向で記述した場合、Djangoが予め用意しているクラス(ジェネリックビュー)を継承する事が出来るので、効率よく開発可能です。

豆知識
オブジェクト指向を理解している場合は、クラスベースビューでviewを記述したほうが、可読性、保守性の面で有利です。
オリジナルのwebアプリを作成する場合でも、そのアプリを構成する要素には、他社のアプリと共通する部分が多々あります。
Djangoは、そういった「全てのWebアプリに共通する要素」を生成するのに便利なクラスを用意しています。
ジェネリックビューの構成について
Djangoが用意しているクラス(ジェネリックビュー)は、「Viewクラス」と「Mixinクラス」を継承しています。
1つのジェネリックビューにつき、Viewクラスは1つしか継承されていません。
一方、Mixinクラスは複数継承する事が出来ます。
ジェネリックビューの種類
Djangoのディレクトリ構成を見ると、以下のディレクトリにジェネリックビューがまとめられています。
django/django/views/generic/
このディレクトリには、以下のモジュールがまとめられています。
- base.py
- dates.py
- detail.py
- edit.py
- list.py
それぞれのモジュールに含まれているクラスが、ジェネリックビューになります。
各モジュールのジェネリックビューについて
各モジュールのジェネリックビューは、以下の2種類に分類する事ができます。
- Viewクラス
- Mixinクラス
Viewクラスは合計で31個、Mixinクラスは合計で14個あります。
Viewクラスは、継承するルールとして、他のViewクラスは1つだけ継承し、Mixinクラスの場合は複数継承します。
ここからは、各モジュールに含まれているクラスの継承関係について確認します。
Viewクラスの継承関係は以下です。
View*
TemplateView*
RedirectView*
BaseDateListView
BaseArchiveIndexView
ArchiveIndexView
BaseYearArchiveView
YearArchiveView
BaseMonthArchiveView
MonthArchiveView
BaseWeekArchiveView
WeekArchiveView
BaseDayArchiveView
DayArchiveView
BaseTodayArchiveView
TodayArchiveView
BaseDateDetailView
DateDetailView
BaseDetailView
DetailView*
BaseDeleteView
DeleteView*
ProcessFormView
BaseFormView
FormView*
BaseCreateView
CreateView*
BaseUpdateView
UpdateView*
BaseListView
ListView*
*マークのついたViewクラスは、使用頻度の高いViewクラスです。
Djangoに定義されているモジュール一覧
django/views/generic/
Djangoの上記フォルダには「Viewクラスが定義されているモジュール」が含まれています。
Viewクラスの詳細機能を把握したい場合は、モジュールのコードを読むと良いです。
base
baseモジュールには、Viewクラスが3個、Mixinクラスが2個定義されています。
ContextMixin
View

豆知識
TemplateResponseMixin
TemplateView(TemplateResponseMixin, ContextMixin, View)
django.views.generic.base.TemplateView
TemplateViewクラスを使用する事で、HTMLテンプレートをクライアントに返す事ができます。Django側でのレンダリングが無い場合は、以下のように記述する事ができます。
#urls.py
from django.views.generic.base import TemplateView
path('', TemplateView.as_view(template_name='index.html'))#index.htmlをテンプレートとして使用する
Django側で特定の値をHTMLテンプレートに与えてレンダリングする場合、以下のように記述する事が出来ます。
#views.py
class MyTemplateView(TemplateView):
template_name = 'index.html' #使用するテンプレートを指定
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['time'] = datetime.now() #テンプレートに渡す値を指定
return context
#urls.py
from .views import MyTemplateView
urlpatterns = [
path('home/', MyTemplateView.as_view(), name='home'),
]

豆知識
テンプレートを表示するクラスです。ホーム画面などに使います。
RedirectView(View)

豆知識
dates
datesモジュールには、Viewクラスが15個、Mixinクラスが5個定義されています。
YearMixin
MonthMixin
DayMixin
WeekMixin
DateMixin
BaseDateListView(MultipleObjectMixin, DateMixin, View)
BaseArchiveIndexView(BaseDateListView)
ArchiveIndexView(MultipleObjectTempleteResponseMixin, BaseArchiveIndexView)
BaseYearArchiveView(YearMixin, BaseDateListView)
YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView)
BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView)
MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView)
BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView)
WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView)
BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView)
DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView)
BaseTodayArchiveView(BaseDayArvhiveView)
TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView)
BaseDateDetailView(YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailView)
DateDetailView(SingleObjectTemplateResponseMixin, BaseDateDetailView)
detail
detailモジュールには、Viewクラスが2個、Mixinクラスが2個定義されています。
SingleObjectMixin(ContextMixin)
BaseDetailView(SingleObjectMixin, View)
SingleObjectTemplateResponseMixin(TemplateResponseMixin)
DetailView(SingleObjectTemplateResponseMixin, BaseDetailView)
django.views.generic.detail.DetailView
#views.py
class HogeDetailView(DetailView):
model = hoge #テンプレートに出力したいモデルを定義する
template_name = 'hoge.html' #使用するテンプレートを定義する
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
views.pyでは、出力するモデルと、テンプレートを指定します。
#urls.py
from .views import HogeDetailView
urlpatterns = [
path('hoge/<int:pk>/', HogeDetailView.as_view(), name='hoge')
]
urls.pyでは、取得したいデータのプライマリキーを指定します。
#hoge.html
{{ object.name }}<br>
{{ object.description }}<br>
{{ object.price }}円<br>
モデルから取り出したデータは、objectに含まれているので、その値をHTMLテンプレートに出力します。
edit
editモジュールには、Viewクラスが9個、Mixinクラスが3個定義されています。
FormMixin(ContextMixin)
ModelFormMixin(FormMixin, SingleObjectMixin)
ProcessFormView(View)
BaseFormView(FormMixin, ProcessFormView)
FormView(TemplateResponseMixin, BaseFormView)

豆知識
BaseCreateView(ModelFormMixin, ProcessFormView)
CreateView(SingleObjectTemplateResponseMixin, BaseCreateView)

豆知識
#views.py
class HogeCreateView(CreateView):
model = Hoge #データを挿入するモデルを指定
fields = ['name', 'description', 'price'] #モデル内の使用するテーブルを指定
template_name = 'add_hoge.html' #使用するHTMLテンプレートを指定
success_url = reverse_lazy('store:list_books') #モデルに書込完了した後に遷移するページを指定。遷移するページの指定は対象モデルに、get_absolute_url=""で指定する事も可能。もしくは、def get_success_url()で定義する事も可能。
def form_valid(self, form): #フォームからデータを送信する際の処理をカスタマイズできる。
form.instance.create_at = datetime.now()
form.instance.update_at = datetime.now()
return super(BookCreateView, self).form_valid(form)
def get_initial(self, **kwargs): #表示時の初期値を設定する事が可能。
initial = super(BookCreateView, self).get_initial(**kwargs)
initial['name'] = 'sample'
return initial
views.pyには、データを挿入するモデル、使用するHTMLテンプレート、データを挿入した後に遷移するページ、初期値、データを挿入する際の追加処理、などを記述します。
#models.py
class Hoge(HogeModel):
name = models.CharField(max_length=255)
description = models.CharField(max_length=1000)
price = models.IntegerField()
class Meta:
#テーブル名をhogeに変更
db_table = 'hoge'
def get_absolute_url(self): #モデルに書込完了した際に遷移させる関数。遷移先の指定は、views.pyでも指定可能。
return reverse_lazy('hoge:detail_hoge', kwargs={'pk': self.pk}) #この場合、https://hoge.com/hoge/detail_hoge/pk/に遷移する。
models.pyには、データ挿入後の遷移メソッド(get_absolute_url)を定義します。
遷移先のURLは、ここで指定する事も出来ますが、views.pyで指定した場合は、そちらが優先されます。
#.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="保存">
</form>
htmlファイルには、csrfトークンを生成するテンプレートタグと、フォームを生成するテンプレート変数を記述します。
BaseUpdateView(ModelFormMixin, ProcessFormView)
UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView)

豆知識
#views.py
class HogeUpdateView(UpdateView):
template_name = 'hoge.html'
model = Hoge
form_class = forms.HogeUpdateForm
def get_success_url(self):
return reverse_lazy('hoge:edit_hoge', kwargs={'pk': self.object.id})
views.pyには、使用するHTMLテンプレートと、モデル、生成するフォームを定義します。
get_success_urlメソッドを設定する事で、モデルを更新した後の遷移先を指定する事ができます。
#models.py
class Hoge(BaseModel):
name = models.CharField(max_length=255)
description = models.CharField(max_length=1000)
price = models.IntegerField()
class Meta:
#テーブル名をhogeに変更
db_table = 'hoge'
def get_absolute_url(self):
return reverse_lazy('store:detail_hoge', kwargs={'pk': self.pk})
models.pyで定義した、get_absolute_urlメソッドで、モデル更新後の遷移先を指定する事ができます。
views.pyでget_success_urlを定義した場合、そちらが遷移先として優先されます。
#.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="更新">
</form>
htmlファイルには生成するフォームを定義します。
#urls.py
urlpatterns = [
path('edit_book/<int:pk>', BookUpdateView.as_view(), name='edit_book')
]
urls.pyでは、更新するデータのpk(プライマリキー)を取得可能にします。
DeletionMixin
DeleteViewCustomDeleteWarning(Warning)

豆知識
BaseDeleteView(DeletionMixin, FormMixin, BaseDetailView)
DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView)
#views.py
class HogeView(DeleteView):
model = Hoge
template_name = 'hoge.html'
success_url = reverse_lazy('hoge:list_hoge')
views.pyには、使用するモデル、HTMLテンプレート、データを削除した後に遷移するURLを指定します。
#urls.py
urlpatterns = [
path('delete_hoge/<int:pk>', HogeDeleteView.as_view(), name='delete_hoge')
]
#.html
<form method="POST">
{% csrf_token %}
<p>{{ object.name }}を削除して宜しいでしょうか</p>
<input type="submit" value="削除する">
</form>
HTMLテンプレートには、テンプレートタグ{% csrf_token %}を記述します。
list
listモジュールには、Viewクラスが2個、Mixinクラスが2個定義されています。
MultipleObjectMixin(ContextMixin)
BaseListView(MultipleObjectMixin, View)
MultipleObjectTemplateResponseMixin(TemplateResponseMixin)
ListView(MultipleObjectTemplateResponseMixin, BaseListView)
django.views.generic.list.ListView
#views.py
class HogeView(ListView):
model = hoge #使用するモデルを指定
template_name = 'hoge.html' #使用するテンプレートを指定
def get_queryset(self): #DBからデータを取り出す方法を指定
qs = super(HogeView, self).get_queryset()
if 'name' in self.kwargs:
qs = qs.filter(name__startswith=self.kwargs['name'])
qs = qs.order_by('-id')
return qs
#urls.py
from .views import HogeView
urlpatterns = [
path('hoge/<name>', HogeView.as_view(), name='hoge'),
]
#hoge.html
<ul>
{% for object in object_list %}
<li>名前:{{ object.name }}</li>
<li>説明:{{ object.description }}</li>
{% endfor %}
</ul>
DBから取り出したデータは、リスト形式で取り出されるので、それを繰り返し処理でHTMLテンプレートに表示する。
著者情報
名前:スカーレット
2010年からWEBサイトやWEBアプリを作成しています。最初は趣味でブログを書いていましたがSEOを勉強するのが楽しくなり、そのままブロガーとして独立しました。その後、記事を書くだけでは物足りなくなり自分でWEBアプリの作成をスタート。現在はブロガー兼プログラマーとして活動しています。このWEBアプリ(ブロトーク)もDjangoで自作しました。ブロトークはブログとSNSを合体させたようなWEBアプリです。ブログを読んで気づいた事や感想などあれば、気軽にメッセージを送って頂ければと思います。WEB技術を一緒に勉強していけたらと思います。
関連記事
投稿No.63
投稿日March 10, 2023
投稿No.68
投稿日March 11, 2023
投稿No.91
投稿日March 30, 2023