1-17. FormViewとCreateViewを使う

今回のテーマは「FormViewとCreateViewを使う」です。前回まで、トピックの作成処理はthread/views.pyにtpic_create関数で処理を書きました。今回はフォームで受けたデータを保存する処理をFormViewをCreateViewを使って書いていきましょう。

※本ページはFormとHTMLレンダリングの関係を理解するまで読まれた方を対象としています。そのためサンプルソースコードが省略されている場合があります。

FormViewを使う

FormViewはTemplateViewを継承したクラスで受け取ったデータの精査の成功と失敗での別々の処理をします。まずはtopic_create関数をFormViewを使って書き直してみましょう。
thread/views.py


from django.shortcuts import render, redirect
from django.views.generic import CreateView, FormView
from django.urls import reverse_lazy

from . forms import TopicCreateForm
from . models import Topic

class TopicFormView(FormView):
    template_name = 'thread/create_topic.html'
    form_class = TopicCreateForm
    success_url = reverse_lazy('base:top')

    def form_valid(self, form):
        form.save()
        return super().form_valid(form)

def topic_create(request):
    template_name = 'thread/create_topic.html'
    ctx = {}
    if request.method == 'GET':
        ctx['form'] = TopicCreateForm()
        return render(request, template_name, ctx)
    
    if request.method == 'POST':
        topic_form = TopicCreateForm(request.POST)
        if topic_form.is_valid():
            topic_form.save()
            return redirect(reverse_lazy('base:top'))
        else:
            ctx['form'] = topic_form
            return render(request, template_name, ctx)

thread/urls.pyも書き直します。
thread/urls.py


urlpatterns = [
    path('create_topic/', views.TopicFormView.as_view(), name='create_topic'),
    # path('create_topic/', views.topic_create, name='create_topic'),
]

これでlocalhost:8080/thread/create_topic/にアクセスしてみましょう。フォームに入力して「作成」ボタンを押すと作成が成功すればTOP画面に遷移するはずです。現段階では作成したトピックが見れないので管理画面で確認しましょう。
トピック登録画面

管理画面で確認

ここで行っている処理自体は書き直す前の関数と同じ処理です。FormViewはTemplateViewを継承しているのでGETで受けた場合にはtemplate_nameで指定されたテンプレートを表示します。その際にform_classで指定されたフォームを’form’という名前でコンテキストとして渡します。POSTされた際にはform_valid関数が呼ばれデータの精査が行われ、成功すればsuccess_urlに遷移します。もし失敗した場合はエラー情報をフォームに格納して再度template_nameのテンプレートを表示します。今回はform_valid関数をオーバーライドして保存処理を行っています。

CreateViewを使ってみる

さて、thread/views.pyの内容をクラスベースビューの1つであるCreateViewを使って書き直してみましょう。CreateViewはFormViewを継承しているのでもっとシンプルに書くことができますよ。

thread/views.py


from django.shortcuts import render, redirect
from django.views.generic import CreateView
from django.urls import reverse_lazy

from . forms import TopicCreateForm
from . models import Topic

class TopicCreateView(CreateView):
    template_name = 'thread/create_topic.html'
    form_class = TopicCreateForm
    model = Topic
    success_url = reverse_lazy('base:top')

当然urls.pyも変更します。
thread/urls.py


from django.urls import path

from . import views
app_name = 'thread'

urlpatterns = [
    path('create_topic/', views.TopicCreateView.as_view(), name='create_topic'),
    # path('create_topic/', views.topic_create, name='create_topic'),
]

CreateViewはGETメソッドで受けた場合にtemplate_nameで指定されたテンプレートを表示します。その際にform_classで指定されたフォームを’form’という名前でコンテキストとして渡します。POSTでデータを受けた際にはformのデータを精査して正しいデータであれば保存処理を行い、success_urlにリダイレクトします。もし正しいデータでなければ、エラー内容を含んだformを渡してtemplate_nameで指定されたテンプレートを表示する。という処理を行います。この処理は最初に出てきたcreate_topic関数と同じ処理を行っていますよね。

最後に

ちょっと混乱してしまったでしょうか?Djangoは関数でガリガリ自分で書くことも出来ますが、目的に応じたプリセットクラスを使うことでよりスマートに書くことも出来ます。次回は確認画面がある登録画面を作成していきます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です