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/

コメントを残す

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