FormViewはフォームを表示したり、フォームの送信を受け取ります。
今回は掲示板風なサイトを作成します。テーブルは以下のようにThreadとResponseからなり、ResponseのtitleはThreadのidと1対多の関係です。

入力画面は以下のようにThreadのタイトルとResponseのtextに対応した2つフォームをテンプレートに渡します。

モデル
test_app/models.py に今回は以下のように記述しました。
from django.db import models # スレッド class Thread(models.Model): title = models.CharField(verbose_name = 'スレッドタイトル', max_length=64) def __str__(self): return self.title # スレッドへのレスポンス class Response(models.Model): title = models.ForeignKey(Thread,on_delete=models.CASCADE, verbose_name = 'スレッドタイトル') text = models.TextField(verbose_name = 'テキスト') post_date = models.DateTimeField(verbose_name = '作成日', auto_now_add=True) def __str__(self): return self.text
View
FormViewを継承した「CreateThreadView」を作成しました。
from django.urls import reverse_lazy # Create your views here. from django.views.generic.edit import FormView from .forms import CreateThreadForm, AddResponseForm from .models import Thread class CreateThreadView(FormView): template_name = "test_app/create_thread.html" model = Thread form_class = CreateThreadForm # テンプレートに渡すデータを作成 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Formのインスタンスを取得 add_response_form = AddResponseForm() create_thread_form = CreateThreadForm() # Formのインスタンスをreturn用の辞書に格納 context = { "add_response_form" : add_response_form, "create_thread_form" : create_thread_form } return context # Formのチェック。問題がなければDBを更新 def form_valid(self, form): # 引数ありのFormインスタンスを作成 create_thread_form = CreateThreadForm(self.request.POST) # Formのチェック if create_thread_form.is_valid(): # threadのインスタンスを作成して保存 thread = create_thread_form.save() # 引数ありのFormインスタンスを作成 add_response_form = AddResponseForm(self.request.POST) # Formのチェック if add_response_form.is_valid(): # responseのインスタンスを作成。まだ保存しない response = add_response_form.save(commit=False) # threadに紐づいているIDを取得 response.title_id = thread.id # 保存 response.save() return super().form_valid(form) def get_success_url(self): return reverse_lazy("create_thread")
ポイントは「get_context_data」で2つのフォームをテンプレートに渡しています。
URL
まだ画面ひとつしか作成していないのでCreateThreadViewのみパスを通しています。
from django.urls import path from .views import CreateThreadView urlpatterns = [ # /にアクセスした時、CreateThreadViewを呼び出す path("", CreateThreadView.as_view(), name="create_thread"), ]
テンプレート
最低限フォームを表示して、送信するだけですが、以下のようにしました。
<form method="post"> {% csrf_token %} <div>スレッドタイトル (CreateThreadFormで作成) </div> <div>{{ create_thread_form.title }}</div><br> <div>最初のレス (AddResponseFormで作成) </div> <div>{{ add_response_form.text }}</div> <button type="submit">Submit</button> </form>
ここまで行えば以下の画面が表示できると思います。

コメント