Djangoのforms.Formでフォームの結果をモデルに保存する方法
Djangoのforms.Formでフォームの結果をモデルに保存する方法をご紹介します。
フォームで入力した内容をモデルに保存する場合、「forms.ModelForm」を用いると簡単です。
しかし、ここではあえて「FormView」と「forms.Form」を使用します。
目次
条件
- Django 3.0.7
- Python 3.7.0
models.py
models.pyに以下のようにPostクラスを追加します。
from django.db import models
class Post(models.Model):
    """投稿モデル"""
    class Meta:
        db_table = 'post'
    title = models.CharField(verbose_name='タイトル', max_length=10)
    comment = models.CharField(verbose_name='コメント', max_length=100)
    created_at = models.DateTimeField(verbose_name='登録日時', auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)
    def __str__(self):
        return self.title + ',' + self.comment
urls.py
トップ画面にフォーム画面を表示します。
from django.urls import path
from . import views
app_name = 'sampleApp'
urlpatterns = [
    # トップ画面
    path('', views.TestView.as_view(), name='index'),
]
forms.py
「forms.Form」のTestFormクラスを定義します。
from django.forms import forms, CharField
from sampleApp.models import Post
class TestForm(forms.Form):
    title = CharField(
        initial='',
        label='タイトル',
        max_length=10,
        required=True,  # 必須
    )
    comment = CharField(
        initial='',
        label='コメント',
        max_length=100,
        required=True,  # 必須
    )
    def save(self):
        # save data using the self.cleaned_data dictionary
        data = self.cleaned_data
        post = Post(title=data['title'], comment=data['comment'])
        post.save()
views.py
「FormView」を用います。
from django.contrib import messages
from django.views.generic.edit import FormView
from sampleApp.forms import TestForm
class TestView(FormView):
    template_name = 'sampleApp/index.html'
    form_class = TestForm
    success_url = '/'  # リダイレクト先URL
    def form_valid(self, form):
        form.save()  # 保存処理など
        messages.add_message(self.request, messages.SUCCESS, '登録しました!')  # メッセージ出力
        return super().form_valid(form)
テンプレート
index.htmlに、「メッセージ」と「フォーム」を表示するようにします。
{% extends 'base.html' %}
{% block content %}
    <h2>フォームサンプル</h2>
    {% if messages %}
    <ul class="messages">
        {% for message in messages %}
        <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
        {% endfor %}
    </ul>
    {% endif %}
    <form method="post">{% csrf_token %}
        {{ form.as_p }}
        <input type="submit" value="送信">
    </form>
{% endblock %}
実行結果
実行前
DBには1レコードのみが存在する状態です。
フォームに値を入力して、送信ボタンを押します。
実行後
views.pyのsuccess_urlで指定したURL(今回はフォームのURLと同一)にリダイレクトして、
「登録しました!」というメッセージが表示されます。
DBに新しいレコードが追加されていることがわかります。
参考
Django公式:FormView
https://docs.djangoproject.com/ja/3.0/ref/class-based-views/generic-editing/#formview
Django公式:フォームとフィールドの検証
https://docs.djangoproject.com/ja/3.0/ref/forms/validation/#form-and-field-validation
Django公式:メッセージフレームワーク
https://docs.djangoproject.com/ja/3.0/ref/contrib/messages/#module-django.contrib.messages
stackoverflow:How do you write a save method for forms in django?
https://stackoverflow.com/questions/11943912/how-do-you-write-a-save-method-for-forms-in-django
Django Girls:Djangoフォーム
https://tutorial.djangogirls.org/ja/django_forms/






