Djangoの司令塔を担うビューの役割についてまとめておこうと思います。
ビューの目的は主に以下4点ですが、ほぼすべてのファイルに対して指示を出しています。
- フォーム処理の指示
- データベース操作の指示
- テンプレートにhtmlの生成を指示
- ルーティングに処理を譲渡し、画面移動を円滑に行う
このビューに関してはDjangoの中でも一番理解しずらい内容であると感じていますが、この記事では理解をできるだけしやすいように(忘れても思い出しやすいように)まとめていますので安心してください。
Djangoのビューが難解に感じる理由は、個人的な意見ですが、
記述方法が「関数ベースビュー」と「クラスベースビュー」の2通りの記述方法があるのが難しく感じる理由であると感じています。
この解決法としては、「クラスベースビュー」で記載することだけを考えることです。
初心者は、「関数ベースビュー」の考え方は捨ててもよいと割りきってください。
ビューの構文を覚える
ビューには以下大事なキーワードがあります。
- クラスベースビュー
- オーバライドするクラス変数
- オーバライドするメゾット
この3つは超重要です。
この3つはそれぞれに決まった機能が複数あるのですが、よく使う機能を覚えておく必要があります。
そもそもクラスベースビューやクラス変数やメゾットって何かについて超ざっくり説明します。
クラスベースビューとは
クラスベースビューとは、pythonのクラス機能を利用して何か処理を行うためのひな型です。そして、このビューで使用するクラスは、まとまった処理クラスを利用できるようにDjangoが提供しているクラスを使用して処理を行うことになります。
オーバーライドするクラス変数とは
クラス変数とは、Djangoの1つのプロジェクト内で共通に使用できる変数のことを指しています。つまり、ビューだけで無く、モデルやテンプレートでも同じそのクラス変数が使えることになります。Djangoがあらかじめ決まった文字列に意味を持たせている為、初心者はまずどんな文字列があるのかを知っておく必要があります。ただし、共通で使用する為には、クラスベースビューごとに決まっているので注意が必要です。
メゾットとは
ひな型であるクラスベースビューの中で特定の処理を行う構文です。def~で始まる構文を指しています。クラス変数と同様で、 共通で使用できるメゾットは、クラスベースビューごとに決まっているので注意が必要です。
クラスベースビューの構文
クラスベースビューの構文について軽く触れておきます。クラスビューは大きく3部「参照ヘッダー」「class ベースビュー」「メゾッド」で構成されています。
参照ヘッダー:viewやform,modelから参照するためのヘッダー(何が必要かは覚えるしかないようです)
クラスベースビュー:行いたい処理に合わせてクラスベースビューを設定する。モデルやテンプレートやフォームとの紐付けがここでなされる。
メゾッド:決まった処理を行う。
クラスベースビューについて説明します。下の表は8つの主なクラスベースビューの例を記載しています。使用例については初心者はまだ見なくてもよいです。
クラスベースビュー | 用途 | 使用例 |
RedirectView | リダイレクトを処理 (特定のページを開く) | from django.views import generic class DjangoRedirectView(generic.RedirectView): url = ‘https://**リダイレクト先のurlを記載**.com/ |
TemplateView | テンプレート表示 テンプレートにhtmlの生成指示 | from django.views import generic class IndexView(generic.TemplateView): template_name = “作成するファイル名.html” |
ListView | モデルオブジェクトの一覧表示 | from django.contrib.auth.mixins import LoginRequiredMixin from .models import Model_A class DjangoListView(LoginRequiredMixin,generic.ListView): model = Model_A template_name = ‘list.html’ def get_queryset(self): app_A = Model_A.objects.filter(user=self.request.user).order_by(‘-created_at’) return app_A |
CreateView | モデルオブジェクトを作成 | from .forms import InquiryForm,App_ACreateForm class appACreateView(LoginRequiredMixin,generic.CreateView): model = Model_A template_name = ‘list.html’ form_class = forms.pyで作るクラス success_url = reverse_lazy(‘appA:appA_list’)←appA_listはurl.pyで作るパス def form_valid(self,form): appA = form.save(commit=False) appA.user = self.request.user appA.save() messages.success(self.request,’モデルを作成しました’) return super().form_valid(form) def form_invalid(self,form): messages.error(self.request,”モデルの作成に失敗しました”) |
DetailView | モデルオブジェクトの詳細表示 | class appADetailView(LoginRequiredMixin,generic.DetailView): model = Model_A template_name = ‘appA_detail.html’ |
UpdateView | モデルオブジェクトの更新 | class appAUpdateView(LoginRequiredMixin,generic.UpdateView): model = Model_A template_name = ‘appA_detail.html’ form_class = appCreateForm def get_success_url(self): return reverse_lazy(‘appA:appA_detail’, kwargs={‘pk’:self.kwargs[‘pk’]}) def form_vaild(self,form): messages.success(self.request,’更新しました’) return super().form_valid(form) def form_invaild(self,form): messages.error(self.request,’更新失敗しました’) return super().form_invalid(form) |
DeleteView | モデルオブジェクトの削除 | class appADeleteView(LoginRequiredMixin,generic.DeleteView): model = Model_A template_name = ‘ appA_list.html’ success_url = reverse_lazy(‘appA:appA_list’) ←appA_listはurl.pyで作るパス def delete(self,request, *args, **kwargs): messages.success(self.request,’モデルを削除しました’) return super().delete(request, *args,**kwargs) |
FormView | フォームに指示 | from django.views import generic from .forms import InquiryForm class IndexView(generic.TemplateView): template_name = ‘ appA_index.html’ class InquiryView(generic.FormView): template_name = ‘ appA_inquiry.html’ form_class = InquiryForm |
まだ初心者の方は上の表にある8つのクラスベースビューを覚えるのがやっとだと思います。当の私も完全に覚えれていませんが、この記事を書きながら学習しています。
さらにオーバーライドできるクラス変数とメゾッドの例をいくつか紹介しておきます。
クラス変数 | 対応できるクラスベースビュー | 用途 | 使用例 |
template_name | RedirectView 以外 | テンプレート名を指定する | template_name = ‘index.html’ |
model | ListView, CreateView, DetailView UpdateView, DeleteView | モデルを指定する querysetを設定していない場合は必須事項 | model = ***Model |
paginate_by | ListView | 1ページに表示する件数を指定する。 | paginate_by = 9 |
queryset | ListView, CreateView, DetailView UpdateView, DeleteView | テンプレートにクエリーセットを modelを使用していない場合は必須。 get_querysetと違い、毎回同じクエリーの時に使える | queryset = *** Model_objects. filter(*** = bar) |
from_class | CreateView, UpdateView FormView | フォームクラス名を指定する。 | form\class = ***Form |
success_url | CreateView, UpdateView FormView | 処理が成功した場合にリダイレクトさせるURLを指定する。 このURLは動的に変化できない。 | success_url = reverse_lazy(‘app:index’) |
get_success_url | CreateView, UpdateView FormView | 処理が成功した場合にリダイレクトさせるURLを指定する。 このURLは動的に変化できる。 | get_success_url = reverse_lazy(‘app:index’) |
fields | CreateView , UpdateView | ビューで使うフォームのフィールドを指定する。 | fields = (‘field1’,field2,) |
そして、代表的なメゾッドを紹介しておきます。
メゾッド | 対応ビュー | 用途 | 使用例 |
get_context_data | RedirectView 以外 | テンプレートに辞書データを渡す際に使用する | def get_context_data(self): context = super().get_context_data() context(‘***’) = ***Model.objects.get(user=self.request.user) return context |
get_queryset | ListView, CreateView, DetailView UpdateView, DeleteView | テンプレートにクエリーセットを渡す。(querysetと違い、クエリーが都度変更となる場合) | def get_queryset(self): *** = ***Model.objects.filter(user = self.request.user) return *** |
form_valid | CreateView, UpdateView FormView | フォームバリデーションに問題がなければ処理を行う。 | def get_vali(self, form): messages.success(self.request,’成功しました’) return super().form_valid(form) |
form_invalid | CreateView, UpdateView FormView | フォームバリデーションに問題があれば処理を行う。 | def get_invali(self, form): messages.error(self.request,’失敗しました’) return super().form_invalid(form) |
get_success_url | CreateView, UpdateView DeleteView, FormView | 処理成功時にリダイレクトするURLを指定する。 | def get_success_url(self): return reverse(‘app:detail’,kwargs={‘pk’:self.kwargs[‘pk’]}) |
delete | DeleteView | 削除処理に合わせて、ほかの処理を実行する。 | def delete(self,request,*args,**kwargs): return super().delete(request,*args,**kwargs) |
get | RedirectView, TemplateView, ListView, CreateView, DetailView, UpdateView, DeleteView, FormView | get通信時の処理を行う | def get(self,request,*args,**kwargs): return HttpResponse(‘Hello World’) |
post | RedirectView, CreateView, UpdateView, DeleteView, FormView | post通信時の処理を行う | def post(self,request,*args,**kwargs): form = self.form_class(request.POST) if not form.is_valid(): return HttpResponseRedirect(reverse_lazy(‘app:index’)) return render(request,self.template_name,{‘form’:form}) |