Computer368106 views
高校倫理1440106 views
高校物理160203 views
数学講師2886227 views
小学算数1200427 views
教育149510 views
高校日本史190571 views
いろは3010814 views
中学英語811710 views
高校化学2924392 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

Django の ModelForm でモデルと連動したフォームを作る

通常の Form クラスではフィールドを 1 つずつ手書きしますが、ModelForm を使えばモデルの定義からフォームを自動生成できます。モデルのフィールドとフォームのフィールドが二重定義にならず、保存処理も .save() 一発で完了するのが大きな利点です。

ModelForm の基本

ModelFormforms.ModelForm を継承し、内部クラス Meta で対象モデルとフィールドを指定します。

from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'body', 'category']

Article モデルの titlebodycategory フィールドに対応するフォームフィールドが自動的に作られます。CharFieldforms.CharField に、ForeignKeyforms.ModelChoiceField に——というように、モデルのフィールド型から適切なフォームフィールドへの変換が行われます。

Form

フィールドを手動で定義する。モデルと無関係なフォーム(検索フォームなど)に向く

ModelForm

モデルからフィールドを自動生成する。CRUD 操作で威力を発揮する

fields と exclude

Meta クラスではフォームに含めるフィールドを明示的に指定します。

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'body', 'category']

fields = '__all__' と書くと全フィールドがフォームに含まれますが、セキュリティ上の理由から推奨されません。ユーザーに編集させたくないフィールド(is_staffis_superuser など)まで含まれてしまう危険があるためです。

逆に、特定のフィールドだけを除外したい場合は exclude を使います。

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        exclude = ['published_at', 'author']

ただし exclude も「将来モデルにフィールドを追加したとき、意図せずフォームに含まれる」リスクがあるため、fields で必要なものだけを列挙する方が安全です。

ビューでの使い方(新規作成)

ModelForm の最大の利点は .save() メソッドです。バリデーション通過後に呼び出すだけで、モデルインスタンスの作成とデータベースへの保存が一括で行われます。

from django.shortcuts import render, redirect
from .forms import ArticleForm

def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('article_list')
    else:
        form = ArticleForm()
    return render(request, 'articles/create.html', {'form': form})

フォームに含まれていないフィールド(例えば author)を保存時にセットしたい場合は、commit=False を使います。

def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save(commit=False)
            article.author = request.user
            article.save()
            return redirect('article_list')
    else:
        form = ArticleForm()
    return render(request, 'articles/create.html', {'form': form})

commit=False はデータベースに保存せずにモデルインスタンスだけを返します。フィールドを手動で追加した後に article.save() を呼び出すことで、不足していた値を補完してから保存できます。

ビューでの使い方(編集)

既存レコードの編集では、instance パラメータに対象オブジェクトを渡します。

from django.shortcuts import render, redirect, get_object_or_404
from .forms import ArticleForm
from .models import Article

def article_edit(request, pk):
    article = get_object_or_404(Article, pk=pk)
    if request.method == 'POST':
        form = ArticleForm(request.POST, instance=article)
        if form.is_valid():
            form.save()
            return redirect('article_detail', pk=article.pk)
    else:
        form = ArticleForm(instance=article)
    return render(request, 'articles/edit.html', {'form': form})

instance=article を渡すことで、フォームは既存データで初期化されます。POST 時にも instance を渡せば、save() は新規作成ではなく更新として動作します。

GET: instance で既存データを初期化して表示

POST: instance と送信データでフォームを構築

save() で既存レコードを更新

widgets と labels のカスタマイズ

Meta クラスで widgetslabels を指定すると、フォームの見た目を調整できます。

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'body', 'category']
        widgets = {
            'title': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'タイトルを入力'
            }),
            'body': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 10
            }),
        }
        labels = {
            'title': '記事タイトル',
            'body': '本文',
            'category': 'カテゴリ',
        }

attrs に辞書を渡すと HTML 属性を追加できます。CSS フレームワーク(Bootstrap など)のクラス名を付けたいときにこの方法がよく使われます。

ModelForm を使うべき場面

モデルのデータを作成・編集するフォームなら、ほぼ確実に ModelForm を使うべきです。フィールドの定義がモデルと同期されるため、モデルを変更したときの修正箇所が減り、.save() による保存処理も簡潔になります。

一方で、検索フォームやログインフォームのようにモデルと 1 対 1 で対応しないフォームには、通常の Form クラスを使います。用途に応じた使い分けが、Django のフォーム設計を見通しよくするポイントです。