【Django】ModelFormとは?書き方から具体例まで解説

Django

(最終更新月:2022年3月)

✔このような方へ向けて書かれた記事となります

「ModelFormって何?Formクラスと何が違うの?」

「ModelFormの書き方、使い方が知りたい!」

「ModelFormを使った具体例が見てみたい。」

✔当記事を通じてお伝えすること

  • ModelFormとは?Formクラスと使い分けるには?
  • ModelFormの基本〜書き方編
  • ModelFormの具体例をお見せします

【著者プロフィール】

profile_icon
【Python歴】11年 x 【Django歴】10年
HP作成、社内システムの構築、コンサルティング

当ブログを通じて、Webアプリの書き方やアプリの公開方法までを解説しています。

☆日報アプリ「D-Repo」(デモ版)→こちら

※Djangoをベースに作成したアプリです。

☆便利ツールアプリ「Tool Station」→こちら

※Django REST frameworkとReactで作成しているアプリです。

✔月9,800円でWebデザインが学べる

デザナルは、Webデザインに苦手意識がある方におすすめのサブスク型スクールです。

特徴は以下の通り。

  • 初期費用不要
  • 教材が使い放題
  • 案件で収入も得られる

デザナルは稼ぎながら学べる、格安のWebデザインスクールです。

>>詳細はこちら<<

安いWebデザインスクール「デザナル」を徹底分析

ModelFormとは?Formクラスとの違いは?

ModelFormとは?

ModelFormとは、既存のモデルと連携されたフォームを作成するためのフォームクラスです。

DjangoのFormクラス同様、formsモジュール内に存在します。

from django.forms import ModelForm

Formクラスとの違いを具体的に見ていくことで理解を深めていきましょう。

Formクラスとの違い|ModelFormのメリット・デメリット

Formクラスの構成

from django import forms

class TestForm(forms.Form):
    field1 = forms.CharField(max_length=255)
    field2 = forms.IntegerField()
    fields3 = ....
    ....

特に既存のモデルとは関係がなく、必要なフィールドを全て記述していきます。

ModelFormクラスの構成

from django import forms

from .models import NippoModel

class TestModelForm(forms.ModelForm):
    class Meta:
        model = NippoModel
        fields = "__all__"

ModelForm内で紐付けたいモデルとそのフィールドを指定します。

ModelFormクラスのメリット

  • フィールド数に関わらず、必要なコードは数行だけ
  • 保存や編集の際も連動して動くため、余計なメソッドの記述が不要

ModelFormクラスのデメリット

  • 紐付けるモデルが必要
  • 自由度が少し低い

対象のモデルが決まっていて、データを保存、編集したい場合はModelFormが適しています。

次章で書き方を見ていきます。

ModelFormの基本 〜 書き方編

ModelFormの書き方

構成としては下記の通りとなります。

from django import forms
from .models import モデル名

class フォームクラス名(forms.ModelForm):
    class Meta:
        model = モデル名
        fileds = "__all__" #表示するフィールドを指定します。

ポイントは3つです。

  1. 継承したクラス内でMetaクラスを定義
  2. model」変数で保存・編集するモデルクラスを指定
  3. fields」変数で使用するフィールドを指定

特に、3.「fields」には下記の通りフィールドを指定します。

#フィールド全て
fields = "__all__"

#フィールドの一部
fields = ["フィールド1", "フィールド2"]

#一部のフィールドを除く
exclude = "user"

ビューの書き方

ビューの書き方としては基本はフォームクラスと同様です。

ただし、form_validメソッドは割愛することも可能です。

from django.views.generic.edit import CreateView
from .forms import フォームクラス名

class ビュークラス名(CreateView):
    template_name = テンプレートパス
    form_class = フォームクラス名
    success_url = URLパス

「Formクラスの書き方を知りたい!」という方はこちらをご覧ください。

ModelFormの使い方〜具体例をお見せします

こちらのモデルを使用して、①CreateView②UpdateViewを作っていきます。

models.py

class NippoModel(models.Model):
    title = models.CharField(max_length=100, verbose_name="タイトル")
    content = models.TextField(max_length=1000, verbose_name="内容")
    public = models.BooleanField(default=False, verbose_name="公開する")
    slug = models.SlugField(max_length=20, unique=True, default=slug_maker)

CreateViewの作成

forms.py

from django import forms
from .models import NippoModel

class NippoModelForm(forms.ModelForm):
    class Meta:
        model = NippoModel
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        for field in self.base_fields.values():
            field.widget.attrs["class"] = "form-control"
        super().__init__(*args, **kwargs)

※__init__関数の箇所では、Bootstrapの「form-control」クラスを各フィールドに適用するためのものです。必ず必要なものではありません。

views.py

from django.views.generic.edit import CreateView

class NippoCreateFormView(CreateView):
    template_name = "nippo/nippo-formclass.html"
    form_class = NippoModelForm
    success_url = reverse_lazy("nippo-list")

ポイントは下記の通りです。

  • CreateViewのインポート
  • 「template_name」「form_class」「success_url」変数へ値を格納
  • form_valid関数は不要

html

{% extends 'base.html' %}

{% block content %}
<div class="container my-3" style="max-width:700px;">
    <div class="text-center my-3">
        <h2>新しく日報を作成</h2>
    </div>
    
    <form method="POST"> {% csrf_token %}
        {{ form.as_p }}
        <button class="btn btn-primary form-control" type="submit">登録</button>
    </form>
</div>
{% endblock %}

urls.py

from django.urls import path
from .views import NippoCreateView

urlpatterns = [
    path("create/", NippoCreateView.as_view(), name="nippo-create"),
]

CreateViewについて詳しく解説を見たい方はこちらをご覧ください。

UpdateViewの作成

同じModelFormを使用します。ModelForm以外のコードを見ていきましょう。

views.py

class NippoUpdateFormView(UpdateView):
    template_name = "nippo/nippo-formclass.html"
    model = NippoModel
    form_class = NippoModelForm
    success_url = reverse_lazy("nippo-list")

html

{% extends 'base.html' %}

{% block content %}
<div class="container my-3" style="max-width:700px;">
    <div class="text-center my-3">
        <h2>日報を編集</h2>
    </div>
    
    <form method="POST"> {% csrf_token %}
        {{ form.as_p }}
        <button class="btn btn-primary form-control" type="submit">編集</button>
    </form>
</div>
{% endblock %}

urls.py

from django.urls import path
from .views import NippoUpdateView

urlpatterns = [
    #...,
    path("update/<slug:slug>/", NippoCreateView.as_view(), name="nippo-update"),
]

まとめ

当記事の内容をまとめます。

ModelFormとは、既存のモデルと連携されたフォームを作成するためのフォームクラスです。

ModelFormクラスの書き方では下記の3つをおさえましょう。

  1. Metaクラスの定義
  2. モデルクラスを指定すること
  3. フィールドを指定すること

さて、当記事のCreateView、UpdateViewは、当ブログを通じて作成中の日報アプリの一部です。

その点でみると、現状2点の修正すべき点が出てきました。

①ラベル元が英語表記になっている②フィールドが自動でinputになってしまっている点です。

Formクラスと同じようにフィールド内でwidgetによる書き換えも可能ですが、今後のことも考えて別の方法をご紹介します。

次回の記事では、models.pyでラベルの書き換え、日本語表記にする方法、を解説していきます。

当記事をご覧の方の中にも「そろそろウェブでアプリを公開してみたいなぁ」「どうやって公開するの?」という方もいらっしゃるのではないでしょうか?
下記の通り、別記事ではDjangoアプリの公開方法公開までの準備についての解説をしていますのでご覧ください!

「Webアプリを公開したい!」という方へ

【保存版】Apache WebサーバーでDjangoアプリを公開
Djangoが公開できる月500円~のレンタルサーバー
【初心者向け】ムームードメインで独自ドメインを取得する3ステップ
【実体験】マイIPの使い方を解説|固定IPアドレスを取得・設定する

当ブログでは、日報アプリ開発を通じて、Webアプリを一から開発し公開するまでを初学者の方でもわかるようにと記事を連載しています

「Djangoでのアプリ開発を学びたい!」
「Djangoで開発したアプリをWebで公開するにはどうするの?」

という方は必見です!

【Django】チュートリアル|日報アプリの開発から公開まで
Djangoのチュートリアルをお探しですか?具体的に「手を動かして作ってみたい!」という方へ向けて、誰でもできる簡易的な日報アプリの開発を通じて、Djangoの様々な機能に触れていくシリーズとなっています。PythonでWebアプリを作りたい方、必見の記事となります!

タイトルとURLをコピーしました