DjangoのFormの初期値の設定方法: initial属性の使い方

312, 2021-08-25

目次

DjangoのFormの初期値の設定方法

Djangoではフォームを使ってユーザーからの情報を便利に扱うことができます。
フォームの各フィールドには初期値を設定することができます。

この記事ではDjangoのフォーム(Form)のフィールドに初期値を設定する方法を解説します。
結論から言うと初期値の設定にはフォームやフィールドの属性initialを使います。
具体的には↓を見ていきます。

  • 前提とするプロジェクト、アプリ

  • Formのコンストラクタに初期値を渡す方法

  • Formの各フィールドに初期値を設定する方法

  • Formの__init__()内で初期値を設定する方法

関連記事
DjangoのFormの値の取得方法: is_validとcleaned_data
Djangoのフォーム(forms.Form)の使い方【Python】
Djangoのformの今どきな作り方【Python, モデルフォーム】

前提とするプロジェクト、アプリ

今回は解説用にmysiteというプロジェクトと、myappというアプリを作ってます。
フォームについては初期値の設定と表示に焦点を当ててコードを書いてますので、改造してPOSTも処理できるコードに変更するなどしてみてください。

またmysite/urls.pyは↓のようになっています。

# mysite/urls.py
from django.contrib import admin
from django.urls import path
from myapp import views


urlpatterns = [
    path('admin/', admin.site.urls),
    path('user/', views.user, name='user'),
    path('book/', views.book, name='book'),
    path('post/', views.post, name='post'),
]

Formのコンストラクタに初期値を渡す方法

Formのコンストラクタに初期値を渡す方法です。
前提とするフォームは↓になります。

from django import forms


class UserForm(forms.Form):
    "ユーザーの情報を扱うフォーム"
    name = forms.CharField(label='名前', max_length=64)
    age = forms.IntegerField(label='年齢')
    weight = forms.FloatField(label='体重')
    height = forms.FloatField(label='身長')
    registed = forms.DateTimeField(label='登録日')
    single = forms.BooleanField(label='独身')

このフォームはユーザーの情報を扱うフォームです。
名前や年齢などのフィールドがあります。

このフォームをオブジェクト(インスタンス)にするにはコンストラクタを呼ぶわけですが、その時にinitital引数に初期値のデータを渡すことでフォームの各フィールドに初期値を設定することが出来ます。

from django.shortcuts import render
from django.utils import timezone
from django.http import HttpResponse
from myapp.forms import UserForm


def user(request):
    if request.method == 'GET':
        # フォームを規定値で初期化
        form = UserForm(initial={
            'name': '匿名',
            'age': 20,
            'weight': 50.3,
            'height': 175.2,
            'registed': timezone.now(),
            'single': True,
        })

        context = { 'form': form }  # コンテキストにフォームを納格
        return render(request, 'myapp/user.html', context)  # 描画
    else:
        return HttpResponse('未実装')

↑のようにビューの中でUserFormをオブジェクト(form)にします。
その時にコンストラクタのinitial引数に初期値を渡します。
初期値を設定したフォームはそのままコンテキスト(context)に保存します。
そしてそのコンテキストを使ってテンプレートファイル(myapp/user.html)を描画すれば、初期値を設定したフォームを描画することが可能です。

描画するテンプレートファイルの内容は↓のようになります。

{# myapp/templates/myapp/user.html #}

<h1>ユーザー登録フォーム</h1>

<form action="{% url 'user' %}" method="POST">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="登録" />
</form>

↑のテンプレートファイルを描画すると↓のような画面になります。

user.png

Formの各フィールドに初期値を設定する方法

フォームを定義するときに各フィールドのコンストラクタの引数initialに初期値を渡しておくと、そのフィールドをその初期値で初期化(表示上の)しておくことが可能です。

# myapp/forms.py
from django import forms
from django.utils import timezone


class BookForm(forms.Form):
    "本の情報を扱うフォーム"
    title = forms.CharField(label='タイトル', max_length=64, initial='無題')
    price = forms.IntegerField(label='価格(円)', initial=2000)
    published = forms.DateTimeField(label='出版日', initial=timezone.now())

↑の場合、titleという本の名前を表現する属性にはinitialに文字列「無題」を渡しています。
こうするとtitleフィールドをその値で初期化することが出来ます。
同様にpricepublishedなどのフィールドも同じように初期値を設定します。

このBookFormは↓のような感じでビューで描画します。

# myapp/views.py
from django.shortcuts import render
from django.http import HttpResponse
from myapp.forms import BookForm


def book(request):
    if request.method == 'GET':
        form = BookForm()  # フォームの作成
        context = { 'form': form }  # コンテキストにフォームを納格
        return render(request, 'myapp/book.html', context)  # 描画
    else:
        return HttpResponse('未実装')

テンプレートファイル(myapp/book.html)は↓のような感じになります。

{# myapp/templates/myapp/book.html #}

<h1>本の登録フォーム</h1>

<form action="{% url 'book' %}" method="POST">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="登録" />
</form>

フォームを描画すると↓のような画面になります。

book.png

フィールドのinitial引数は公式のソースコード内のコメントでは↓のように説明されています。

initial -- A value to use in this Field's initial display. This value is not used as a fallback if data isn't given.

日本語にすると「値はフィールドの初期表示で使われます。データが与えられていない場合のフォールバックとして値は使われません」という意味になります。

Formの__init__()内で初期値を設定する方法

フォームの__init__()メソッド(コンストラクタ)を上書きして、そのメソッドの中で各フィールドに初期値を設定するには↓のようなコードを書きます。

from django import forms


class PostForm(forms.Form):
    "掲示板への投稿情報を扱うフォーム"
    name = forms.CharField(label='名前')
    content = forms.CharField(label='内容', widget=forms.Textarea)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['name'].initial = '匿名'
        self.fields['content'].initial = '本文なし'

__init__()の中でself.fields属性にアクセスします。
self.fields[]に参照したいフィールド名を文字列で指定して、そのフィールドのinitial属性に初期値を設定します。
こうすることで各フィールドに初期値を設定することが出来ます。

このフォーム(PostForm)をビューで利用するには↓のようなコードを書きます。

from django.shortcuts import render
from django.http import HttpResponse
from myapp.forms import PostForm


def post(request):
    if request.method == 'GET':
        form = PostForm()  # フォームの作成
        context = { 'form': form }  # コンテキストにフォームを納格
        return render(request, 'myapp/post.html', context)  # 描画
    else:
        return HttpResponse('未実装')

テンプレートファイル(myapp/post.html)は↓のようにします。

{# myapp/templates/myapp/post.html #}

<h1>投稿フォーム</h1>

<form action="{% url 'post' %}" method="POST">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="投稿" />
</form>

このフォームを描画すると↓のような画面になります。

post.png

おわりに

今回はDjangoのフォームの初期値の設定方法について詳しく見てみました。
Djangoのフォームに初期値を設定しておきたいケースはわりと多いかと思います。
initialというキーワードを心のどこかにとどめておいてください。

困ったらinitial

initial D (Django)