---
title: "モデルからフォームを作成する"
version: 2.2
locale: ja
source: https://docs.djangoproject.com/ja/2.2/topics/forms/modelforms/
canonical: https://djangodocs.dev/ja/2.2/topics/forms/modelforms/
---
# モデルからフォームを作成する

## `ModelForm`

#### `class ModelForm`

データベース中心のアプリケーションを作成している場合、Django モデルに密接にマップするフォームを使うことになるでしょう。例えば、`BlogComment` モデルを持っていて、閲覧者がコメントを送信できるフォームを作成したくなったとしましょう。この場合、すでにモデル内にフィールドが定義されているので、フォーム内にフィールドタイプを改めて定義するのは冗長でしょう。

このためDjango には、Django モデルから `Form` クラスを生成できるようなヘルパークラスを用意してあります。

例:

```
>>> from django.forms import ModelForm
>>> from myapp.models import Article

# Create the form class.
>>> class ArticleForm(ModelForm):
...     class Meta:
...         model = Article
...         fields = ['pub_date', 'headline', 'content', 'reporter']

# Creating a form to add an article.
>>> form = ArticleForm()

# Creating a form to change an existing article.
>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(instance=article)
```

### フィールドの型

生成された `Form` クラスは、指定された全てのモデルフィールドに対して、`fields` 属性で指定された順番でフォームフィールドを有します。

各モデルフィールドは、対応するデフォルトのフォームフィールドを持ちます。例えば、モデル上の `CharField`  はフォーム上で `CharField` として表現されます。モデル `ManyToManyField` は `MultipleChoiceField` として表現されます。 以下は、各フィールドの対応表です:

| モデルフィールド | フォームフィールド |
| --- | --- |
| [`AutoField`](/ja/2.2/ref/models/fields/#django.db.models.AutoField) | フォーム上では表示されません。 |
| [`BigAutoField`](/ja/2.2/ref/models/fields/#django.db.models.BigAutoField) | フォーム上では表示されません。 |
| [`BigIntegerField`](/ja/2.2/ref/models/fields/#django.db.models.BigIntegerField) | [`IntegerField`](/ja/2.2/ref/forms/fields/#django.forms.IntegerField) で `min_value` が -9223372036854775808 から `max_value` に 9223372036854775807 セットされます。 |
| [`BinaryField`](/ja/2.2/ref/models/fields/#django.db.models.BinaryField) | [`editable`](/ja/2.2/ref/models/fields/#django.db.models.Field.editable) がモデルフィールド上で `True` にセットされていた場合、[`CharField`](/ja/2.2/ref/forms/fields/#django.forms.CharField) です。それ以外の場合フォーム内で描画されません。 |
| [`BooleanField`](/ja/2.2/ref/models/fields/#django.db.models.BooleanField) | [`BooleanField`](/ja/2.2/ref/forms/fields/#django.forms.BooleanField) です。`null=True` の場合は [`NullBooleanField`](/ja/2.2/ref/forms/fields/#django.forms.NullBooleanField) です。 |
| [`CharField`](/ja/2.2/ref/models/fields/#django.db.models.CharField) | [`CharField`](/ja/2.2/ref/forms/fields/#django.forms.CharField) で、`max_length` はモデルフィールドの `max_length` にセットされます。また `null=True` の場合 [`empty_value`](/ja/2.2/ref/forms/fields/#django.forms.CharField.empty_value) が `None` にセットされます。 |
| [`DateField`](/ja/2.2/ref/models/fields/#django.db.models.DateField) | [`DateField`](/ja/2.2/ref/forms/fields/#django.forms.DateField) |
| [`DateTimeField`](/ja/2.2/ref/models/fields/#django.db.models.DateTimeField) | [`DateTimeField`](/ja/2.2/ref/forms/fields/#django.forms.DateTimeField) |
| [`DecimalField`](/ja/2.2/ref/models/fields/#django.db.models.DecimalField) | [`DecimalField`](/ja/2.2/ref/forms/fields/#django.forms.DecimalField) |
| [`DurationField`](/ja/2.2/ref/models/fields/#django.db.models.DurationField) | [`DurationField`](/ja/2.2/ref/forms/fields/#django.forms.DurationField) |
| [`EmailField`](/ja/2.2/ref/models/fields/#django.db.models.EmailField) | [`EmailField`](/ja/2.2/ref/forms/fields/#django.forms.EmailField) |
| [`FileField`](/ja/2.2/ref/models/fields/#django.db.models.FileField) | [`FileField`](/ja/2.2/ref/forms/fields/#django.forms.FileField) |
| [`FilePathField`](/ja/2.2/ref/models/fields/#django.db.models.FilePathField) | [`FilePathField`](/ja/2.2/ref/forms/fields/#django.forms.FilePathField) |
| [`FloatField`](/ja/2.2/ref/models/fields/#django.db.models.FloatField) | [`FloatField`](/ja/2.2/ref/forms/fields/#django.forms.FloatField) |
| [`ForeignKey`](/ja/2.2/ref/models/fields/#django.db.models.ForeignKey) | [`ModelChoiceField`](/ja/2.2/ref/forms/fields/#django.forms.ModelChoiceField)<br>(see below) |
| [`ImageField`](/ja/2.2/ref/models/fields/#django.db.models.ImageField) | [`ImageField`](/ja/2.2/ref/forms/fields/#django.forms.ImageField) |
| [`IntegerField`](/ja/2.2/ref/models/fields/#django.db.models.IntegerField) | [`IntegerField`](/ja/2.2/ref/forms/fields/#django.forms.IntegerField) |
| `IPAddressField` | `IPAddressField` |
| [`GenericIPAddressField`](/ja/2.2/ref/models/fields/#django.db.models.GenericIPAddressField) | [`GenericIPAddressField`](/ja/2.2/ref/forms/fields/#django.forms.GenericIPAddressField) |
| [`ManyToManyField`](/ja/2.2/ref/models/fields/#django.db.models.ManyToManyField) | [`ModelMultipleChoiceField`](/ja/2.2/ref/forms/fields/#django.forms.ModelMultipleChoiceField) (以下を参照) |
| [`NullBooleanField`](/ja/2.2/ref/models/fields/#django.db.models.NullBooleanField) | [`NullBooleanField`](/ja/2.2/ref/forms/fields/#django.forms.NullBooleanField) |
| [`PositiveIntegerField`](/ja/2.2/ref/models/fields/#django.db.models.PositiveIntegerField) | [`IntegerField`](/ja/2.2/ref/forms/fields/#django.forms.IntegerField) |
| [`PositiveSmallIntegerField`](/ja/2.2/ref/models/fields/#django.db.models.PositiveSmallIntegerField) | [`IntegerField`](/ja/2.2/ref/forms/fields/#django.forms.IntegerField) |
| [`SlugField`](/ja/2.2/ref/models/fields/#django.db.models.SlugField) | [`SlugField`](/ja/2.2/ref/forms/fields/#django.forms.SlugField) |
| [`SmallIntegerField`](/ja/2.2/ref/models/fields/#django.db.models.SmallIntegerField) | [`IntegerField`](/ja/2.2/ref/forms/fields/#django.forms.IntegerField) |
| [`TextField`](/ja/2.2/ref/models/fields/#django.db.models.TextField) | [`CharField`](/ja/2.2/ref/forms/fields/#django.forms.CharField) で `widget=forms.Textarea` です。 |
| [`TimeField`](/ja/2.2/ref/models/fields/#django.db.models.TimeField) | [`TimeField`](/ja/2.2/ref/forms/fields/#django.forms.TimeField) |
| [`URLField`](/ja/2.2/ref/models/fields/#django.db.models.URLField) | [`URLField`](/ja/2.2/ref/forms/fields/#django.forms.URLField) |
| [`UUIDField`](/ja/2.2/ref/models/fields/#django.db.models.UUIDField) | [`UUIDField`](/ja/2.2/ref/forms/fields/#django.forms.UUIDField) |

お気付きかもしれませんが、 `ForeignKey` と `ManyToManyField` の 2 つのモデルフィールドは特殊なケースとなります:

- `ForeignKey` は `django.forms.ModelChoiceField` によって表現され、モデルの `QuerySet` を選択肢として持つ `ChoiceField` です。
- `ManyToManyField` は `django.forms.ModelMultipleChoiceField` によって表現され、モデルの `QuerySet` を選択肢として持つ `MultipleChoiceField` です。

加えて、生成されたフォームフィールドはそれぞれ以下の通り属性がセットされます:

- モデルフィールドに `blank=True` が設定されている場合、フォームフィールド上で `required` が `False` にセットされます。それ以外の場合は `required=True` となります。
- フォームフィールドの `label` はモデルフィールドの `verbose_name` の最初の文字を大文字にしたものがセットされます。
- フォームフィールドの `help_text` はモデルフィールドの `help_text` がセットされます。
- モデルフィールドに `choices` が設定されている場合、フォームフィールドの `widget` は `Select` にセットされ、選択肢にはモデルフィールドの `choices` が使われます。通常、選択肢には空欄の選択肢が追加され、デフォルトで選択されることになります。フィールドが required の場合、ユーザは選択肢を選ぶ必要があります。モデルフィールドに `blank=False` および明示的な `default` 値が設定されている場合、空欄の選択肢は表示されません (代わりに `default` 値が選択された状態で表示されます) 。

与えられたモデルフィールドに対して使われるフォームフィールドをオーバーライドすることもできます。後述の [Overriding the default fields](#overriding-the-default-fields) を参照してください。

### 完全な具体例

以下のような一連のモデルを考えていきましょう:

```
from django.db import models
from django.forms import ModelForm

TITLE_CHOICES = [
    ('MR', 'Mr.'),
    ('MRS', 'Mrs.'),
    ('MS', 'Ms.'),
]

class Author(models.Model):
    name = models.CharField(max_length=100)
    title = models.CharField(max_length=3, choices=TITLE_CHOICES)
    birth_date = models.DateField(blank=True, null=True)

    def __str__(self):
        return self.name

class Book(models.Model):
    name = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ['name', 'title', 'birth_date']

class BookForm(ModelForm):
    class Meta:
        model = Book
        fields = ['name', 'authors']
```

これらのモデルでは、上記の `ModelForm` サブクラスはおおむね以下と同等と言えます (唯一の違いは `save()` メソッドで、これからすぐ説明します):

```
from django import forms

class AuthorForm(forms.Form):
    name = forms.CharField(max_length=100)
    title = forms.CharField(
        max_length=3,
        widget=forms.Select(choices=TITLE_CHOICES),
    )
    birth_date = forms.DateField(required=False)

class BookForm(forms.Form):
    name = forms.CharField(max_length=100)
    authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
```

### `ModelForm` の検証 (バリデーション)

`ModelForm` のバリデーションには、以下の 2 つのステップが存在します:

1. [フォームのバリデーションを実施する](/ja/2.2/ref/forms/validation/)
2. [モデルのインスタンスのバリデーションを実施する](/ja/2.2/ref/models/instances/#validating-objects)

通常のフォームのバリデーションと同じように、モデルフォームのバリデーションは [`is_valid()`](/ja/2.2/ref/forms/api/#django.forms.Form.is_valid) が呼ばれたときや [`errors`](/ja/2.2/ref/forms/api/#django.forms.Form.errors) 属性にアクセスしたとき、暗黙的に実行されます。また、実際にはあまり使うメソッドではありませんが、明示的に `full_clean()` を呼んだときにもバリデーションが実行されます。

`Model` バリデーション ([`Model.full_clean()`](/ja/2.2/ref/models/instances/#django.db.models.Model.full_clean)) は、フォームバリデーションのステップ内でフォームの `clean()` メソッドが呼ばれたすぐ直後に実行されます。

> **Warning**
>
> クリーニングのプロセスは、様々な方法で `ModelForm` コンストラクタに渡されたモデルのインスタンスを修正します。例えば、モデル上のあらゆる日付フィールドは、実際の date オブジェクトに変換されます。失敗したバリデーションは、一貫性のない状態でモデルインスタンスを元のままにしておくため、これを再利用するのはお勧めできません。

#### clean() メソッドをオーバーライドする

通常のフォームと同じ方法でモデルフォーム上の `clean()` メソッドをオーバーライドして、バリデーションの動作を追加することができます。

モデルのオブジェクトに付属したモデルフォームのインスタンスは、`instance` 属性を持ち、メソッドが特定のモデルのインスタンスにアクセスできるようにします。

> **Warning**
>
> `ModelForm.clean()` メソッドは、[モデルバリデーション](/ja/2.2/ref/models/instances/#validating-objects) に、`unique`、`unique_together` または `unique_for_date|month|year` としてマークされたモデルフィールドの一意性を検証させます。
>
> `clean()` メソッドをオーバーライドして、なおかつこのバリデーションを維持したい場合、親クラスの `clean()` メソッドを呼ぶ必要があります。

#### モデルバリデーションとのやり取り

バリデーションプロセスの一部として、`ModelForm` フォーム上で対応するフィールドを持つモデルのそれぞれのフィールドの `clean()` メソッドを呼び出します。モデルフィールドを除外した場合、これらのフィールドに対してはバリデーションが実行されません。フィールドのクリーニングとバリデーションの詳しい働き方については、[フォームバリデーション](/ja/2.2/ref/forms/validation/) ドキュメントを参照してください。

モデルの `clean()` メソッドは一意性のチェックがされる前に呼び出されます。モデルの `clean()` フックのより詳しい情報については、[オブジェクトのバリデーションを行う](/ja/2.2/ref/models/instances/#validating-objects) を参照してください。

#### モデルの `error_messages` のレンダリングを考える

[`フォームフィールド`](/ja/2.2/ref/forms/fields/#django.forms.Field.error_messages) や [フォーム Meta](#modelforms-overriding-default-fields) のレベルで定義されたエラーメッセージは、常に [`モデルフィールド`](/ja/2.2/ref/models/fields/#django.db.models.Field.error_messages) のレベルで定義されたエラーメッセージより優先されます。

[`モデルフィールド`](/ja/2.2/ref/models/fields/#django.db.models.Field.error_messages) で定義されたエラーメッセージは、[モデルバリデーション](/ja/2.2/ref/models/instances/#validating-objects) のステップの間に `ValidationError` が発生したときに、対応するエラーメッセージがフォームのレベルで定義されていない場合にのみ使用されます。

[`NON_FIELD_ERRORS`](/ja/2.2/ref/exceptions/#django.core.exceptions.NON_FIELD_ERRORS) キーを `Meta` クラス内の `error_messages` ディクショナリに追加することで、モデルバリデーションによって発生する `NON_FIELD_ERRORS` に対するエラーメッセージをオーバーライドできます。

```
from django.core.exceptions import NON_FIELD_ERRORS
from django.forms import ModelForm

class ArticleForm(ModelForm):
    class Meta:
        error_messages = {
            NON_FIELD_ERRORS: {
                'unique_together': "%(model_name)s's %(field_labels)s are not unique.",
            }
        }
```

### `save()` メソッド

全ての `ModelForm` は `save()` メソッドも持っています。このメソッドは、フォームに結びつけられたデータからデータベースオブジェクトを生成して保存します。`ModelForm` のサブクラスはキーワード引数 `instance` として既存のモデルインスタンスを受け取ることができます; これが指定されると、`save()` はそのインスタンスを更新するようになります。 指定されない場合は、`save()` は指定されたモデルの新しいインスタンスを生成します:

```python
>>> from myapp.models import Article
>>> from myapp.forms import ArticleForm

# Create a form instance from POST data.
>>> f = ArticleForm(request.POST)

# Save a new Article object from the form's data.
>>> new_article = f.save()

# Create a form to edit an existing Article, but use
# POST data to populate the form.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(request.POST, instance=a)
>>> f.save()
```

フォームが [バリデーションされていない](#validation-on-modelform) 場合、`save()` を呼び出すと、`form.errors` をチェックすることでこれを行います。フォーム内のデータが適正ではない場合は `ValueError` が発生します -- 例えば、`form.errors` が `True` だと評価された場合です。

オプションのフィールドがフォームのデータに表示されない場合、結果のモデルインスタンスはモデルフィールドの [`default`](/ja/2.2/ref/models/fields/#django.db.models.Field.default) を使用します。この動作は、 [`CheckboxInput`](/ja/2.2/ref/forms/widgets/#django.forms.CheckboxInput), [`CheckboxSelectMultiple`](/ja/2.2/ref/forms/widgets/#django.forms.CheckboxSelectMultiple), または [`SelectMultiple`](/ja/2.2/ref/forms/widgets/#django.forms.SelectMultiple) (または [`value_omitted_from_data()`](/ja/2.2/ref/forms/widgets/#django.forms.Widget.value_omitted_from_data) メソッドが常に `False` を返すカスタムウィジェット) を使用するフィールドには適用されません。チェックされていないチェックボックスと、選択されていない `<select multiple>` は HTML フォーム送信のデータには表示されないからです。 API を設計していて、これらのウィジェットを使用するフィールドのデフォルトのフォールバック動作が必要な場合は、カスタムフォームフィールドまたはウィジェットを使用します。

この `save()` には、省略可能な `commit` キーワード引数があり、`True` ないし `False` を取ります。`save()` を `commit=False` で呼び出した場合、データベースにまだ保存されていないオブジェクトを返します。この場合、結果のモデルインスタンスで `save()` を呼び出すかどうかはあなた次第です。これは、保存前にオブジェクトで独自のプロセスを実行したい場合、もしくは特別な [モデル保存オプション](/ja/2.2/ref/models/instances/#ref-models-force-insert) を使いたい場合に有用です。 `commit` はデフォルトでは `True` です。

`commit=False` を使う際のもう 1 つの副作用は、モデルに他のモデルとの多対多の関係がある場合に見られます。フォームを save するときにモデルに多対多の関係があり `commit=False` を指定した場合、Django は多対多の関係に対してフォームのデータを即座に保存することができません。これは、インスタンスがデータベース上に存在するようになるまで、インスタンスに対して多対多のデータを保存することが不可能だからです。

この問題を扱うために、`commit=False` を使ったフォームを save するたびに、Django は `save_m2m()` メソッドをあなたの `ModelForm` サブクラスに追加します。フォームによって生成されたインスタンスを手動で save した後に、多対多のフォームデータを保存するために `save_m2m()` を実行することができます。例えば:

```python
# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

# Now, save the many-to-many data for the form.
>>> f.save_m2m()
```

`save_m2m()` の呼び出しは、`save(commit=False)` を使った場合にのみ必要となります。フォーム上で単に `save()` を使用したときは、全てのデータ -- 多対多のデータを含む -- が追加的なメソッドを呼び出す必要なく保存されます。例えば:

```python
# Create a form instance with POST data.
>>> a = Author()
>>> f = AuthorForm(request.POST, instance=a)

# Create and save the new author instance. There's no need to do anything else.
>>> new_author = f.save()
```

`save()` と `save_m2m()` メソッドのほかは、`ModelForm` は `forms` のフォームとまったく同じ方法で動作します。例えば、`is_valid()` メソッドは妥当性をチェックするために使用される、`is_multipart()` メソッドはフォームがマルチパートのファイルアップロードを必要とするかどうかを (ゆえに `request.FILES` がフォームに渡される必要があるかどうかも) 決める、などです。詳しくは [Binding uploaded files to a form](/ja/2.2/ref/forms/api/#binding-uploaded-files) を参照してください。

### 使うフィールドを選択する

`fields` 属性を使って、フォームで編集すべき全てのフィールドを明示的に指定することを強くお勧めします。そうしないと、フォームで予期せず特定のフィールドを設定できるようになり、セキュリティ上の問題が発生しやすくなります。特に新しいフィールドがモデルに追加されたときに起こりがちです。フォームのレンダリング方法によっては、Webページで問題が目に見えないことさえあります。

代わりの方法は、全てのフィールドを自動的に含めるか、いくつかのフィールドのみをブラックリスト化することです。この基本的なアプローチは安全性が低く、主要なウェブサイトで深刻な悪用 (例えば [GitHub](https://github.com/blog/1068-public-key-security-vulnerability-and-mitigation)) を招いていることが知られています。

しかしながら、これらのセキュリティ問題が当てはまらないことが明白な場合のために、2 つのショートカットが利用可能です:

1. `fields` 属性に、特殊な値 `'__all__'` をセットして、モデル内の全てのフィールドが使われるように指定します。例えば:

   ```
   from django.forms import ModelForm

   class AuthorForm(ModelForm):
       class Meta:
           model = Author
           fields = '__all__'
   ```
2. `ModelForm` の中の `Meta` クラスの `exclude` 属性に、フォームから除外されるフィールドのリストをセットします。

   例:

   ```
   class PartialAuthorForm(ModelForm):
       class Meta:
           model = Author
           exclude = ['title']
   ```

   `Author` モデルは 3 つのフィールド `name`、`title`、`birth_date` を持っているため、これで `name` と `birth_date` がフォームに表示されることになります。

このどちらかが使われた場合、フォーム内で表示されるフィールドの順番はモデル内でフィールドが定義された順番となり、`ManyToManyField` インスタンスは最後に表示されます。

加えて、Django は以下のルールも適用します: モデルフィールドで `editable=False` をセットした場合、`ModelForm` を通じて生成された *全ての* フォームはそのフィールドを含みません。

> **Note**
>
> 上記のロジックでフォームに含まれない全てのフィールドは、フォームの `save()` メソッドでセットされません。また、除外したフィールドを手動でフォームに追加し直した場合、モデルインスタンスから初期化されることはありません。
>
> Django は不完全なモデルを保存しないようにするため、モデルの設定でフィールドを空にすることを許容しておらず、かつ除外されたフィールドに対するデフォルト値を指定しなかった場合、除外されたフィールドを含む `ModelForm` を `save()` しようとすると失敗します。この失敗を避けるには、除外する必須フィールドに初期値を指定してモデルをインスタンス化する必要があります:
>
> ```
> author = Author(title='Mr')
> form = PartialAuthorForm(request.POST, instance=author)
> form.save()
> ```
>
> もしくは、`save(commit=False)` を使って手動で追加の必須フィールドをセットできます:
>
> ```
> form = PartialAuthorForm(request.POST)
> author = form.save(commit=False)
> author.title = 'Mr'
> author.save()
> ```
>
> `save(commit=False)` の使用について、詳しくは [section on saving forms](#the-save-method) を参照してください。

### デフォルトのフィールドをオーバライドする

前述の [Field types](#field-types) テーブルで説明したとおり、デフォルトのフィールドタイプは実用的なデフォルトです。モデルに `DateField` がある場合、フォーム内で `DateField` として表示したいことでしょう。しかし、`ModelForm` では、与えられたモデルに足してフォームフィールドを変更する柔軟性があります。

フィールドに対して独自のウィジェットを指定するには、内部の `Meta` クラスの `widgets` を使用してください。これは、フィールド名としジェットのクラスやインスタンスをマッピングするディクショナリです。

例えば、`Authoer` の `name` 属性に対する `CharField` を、デフォルトの `<input type="text">` の代わりに `<textarea>` で表示したい場合、フィールドのウィジェットをオーバーライドすることができます:

```
from django.forms import ModelForm, Textarea
from myapp.models import Author

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title', 'birth_date')
        widgets = {
            'name': Textarea(attrs={'cols': 80, 'rows': 20}),
        }
```

The `widgets` dictionary accepts either widget instances (e.g.,
`Textarea(...)`) or classes (e.g., `Textarea`). Note that the `widgets`
dictionary is ignored for a model field with a non-empty `choices` attribute.
In this case, you must override the form field to use a different widget.

同様に、フィールドをさらにカスタマイズしたい場合、内部の `Meta` クラスの `labels`、`help_texts`、`error_messages` と言った属性を指定することができます。

例えば、`name` フィールドに対する文字列に直面する全てのユーザの文章をカスタマイズしたい場合:

```
from django.utils.translation import gettext_lazy as _

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title', 'birth_date')
        labels = {
            'name': _('Writer'),
        }
        help_texts = {
            'name': _('Some useful help text.'),
        }
        error_messages = {
            'name': {
                'max_length': _("This writer's name is too long."),
            },
        }
```

`field_classes` を指定して、フォームによってインスタンス化されたフィールドのタイプをカスタマイズすることもできます。

例えば、`slug` フィールドに対して `MySlugFormField` を使いたい場合、以下のようにできます:

```
from django.forms import ModelForm
from myapp.models import Article

class ArticleForm(ModelForm):
    class Meta:
        model = Article
        fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']
        field_classes = {
            'slug': MySlugFormField,
        }
```

最後に、フィールドを完全に -- タイプ、バリデータ、必須かどうかなどを含めて -- コントロールしたい場合、通常の `Form` で行うのと同じようにフィールドを宣言的に指定することで実現できます。

フィールドのバリデータを指定したい場合、フィールドを宣言的に定義して `validators` パラメータを設定することで実現できます:

```
from django.forms import CharField, ModelForm
from myapp.models import Article

class ArticleForm(ModelForm):
    slug = CharField(validators=[validate_slug])

    class Meta:
        model = Article
        fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']
```

> **Note**
>
> 以下のように明示的にフォームフィールドをインスタンス化したとき、`ModelForm` と 通常の `Form` が連動する方法を理解することが重要となります。
>
> `ModelForm` は、特定のフィールドを自動的に生成できる通常の `Form` です。自動的に生成されるフィールドは、`Meta` クラスの内容とどのフィールドが宣言的に定義されているかに依存します。基本的に、`ModelForm` は フォームから **除外された** フィールド、言い換えると宣言的に定義されなかったフィールド **のみ** を生成します。
>
> 宣言的に定義されたフィールドはそのままになります。したがって、`Meta` 属性に対するカスタマイズ、例えば `widgets`、`labels`、`help_texts`、`error_messages` は無視されます; これらは自動的に生成されたフィールドにのみ適用されます。
>
> 同様に、宣言的に定義されたフィールドは、対応するモデルから引き継がれた `max_length` や `required` のような属性を描画しません。モデル内で定義された動作を引き継ぎたい場合は、フォームフィールドを宣言する際に明示的に関連する属性をセットする必要があります。
>
> 例えば、`Article` モデルは以下のようになります:
>
> ```
> class Article(models.Model):
>     headline = models.CharField(
>         max_length=200,
>         null=True,
>         blank=True,
>         help_text='Use puns liberally',
>     )
>     content = models.TextField()
> ```
>
> そして、指定されたとおりに `blank` と `help_text` が維持されている一方で、`headline` に対して独自のバリデーションを実施するために、`ArticleForm` を以下のように定義します:
>
> ```
> class ArticleForm(ModelForm):
>     headline = MyFormField(
>         max_length=200,
>         required=False,
>         help_text='Use puns liberally',
>     )
>
>     class Meta:
>         model = Article
>         fields = ['headline', 'content']
> ```
>
> フォームフィールドのタイプを使用して、対応するモデルフィールドの内容を設定できることを確認する必要があります。 互換性がない場合、暗黙的な変換が行われないので、 "ValueError" を取得します。
>
> フィールドとその属性について、詳しくは [フォームフィールドのドキュメンテーション](/ja/2.2/ref/forms/fields/) を参照してください。

### フィールドのローカル化を有効にする

デフォルトでは、`ModelForm` 内のフィールドはデータをローカル化しません。フィールドに対してローカル化を有効にするために、`Meat` クラスの `localized_fields` 属性を使うことができます。

```
>>> from django.forms import ModelForm
>>> from myapp.models import Author
>>> class AuthorForm(ModelForm):
...     class Meta:
...         model = Author
...         localized_fields = ('birth_date',)
```

`localized_fields` が特殊な値 `'__all__'` にセットされた場合、全てのフィールドがローカル化されます。

### フォームの継承

As with basic forms, you can extend and reuse `ModelForms` by inheriting
them. This is useful if you need to declare extra fields or extra methods on a
parent class for use in a number of forms derived from models. For example,
using the previous `ArticleForm` class:

```
>>> class EnhancedArticleForm(ArticleForm):
...     def clean_pub_date(self):
...         ...
```

This creates a form that behaves identically to `ArticleForm`, except there's
some extra validation and cleaning for the `pub_date` field.

You can also subclass the parent's `Meta` inner class if you want to change
the `Meta.fields` or `Meta.exclude` lists:

```
>>> class RestrictedArticleForm(EnhancedArticleForm):
...     class Meta(ArticleForm.Meta):
...         exclude = ('body',)
```

This adds the extra method from the `EnhancedArticleForm` and modifies
the original `ArticleForm.Meta` to remove one field.

There are a couple of things to note, however.

- Normal Python name resolution rules apply. If you have multiple base
  classes that declare a `Meta` inner class, only the first one will be
  used. This means the child's `Meta`, if it exists, otherwise the
  `Meta` of the first parent, etc.
- It's possible to inherit from both `Form` and `ModelForm` simultaneously,
  however, you must ensure that `ModelForm` appears first in the MRO. This is
  because these classes rely on different metaclasses and a class can only have
  one metaclass.
- It's possible to declaratively remove a `Field` inherited from a parent class by
  setting the name to be `None` on the subclass.

  You can only use this technique to opt out from a field defined declaratively
  by a parent class; it won't prevent the `ModelForm` metaclass from generating
  a default field. To opt-out from default fields, see
  [使うフィールドを選択する](#modelforms-selecting-fields).

### Providing initial values

通常のフォームと同様に、フォームをインスタンス化する際に `initial` パラメータを指定することで、フォームに対する初期値を指定することができます。この方法で提供された初期値は、 フォームフィールドによる初期値と結びついたモデルインスタンスからの初期値の両方をオーバーライドします。例えば:

```
>>> article = Article.objects.get(pk=1)
>>> article.headline
'My headline'
>>> form = ArticleForm(initial={'headline': 'Initial headline'}, instance=article)
>>> form['headline'].value()
'Initial headline'
```

### ModelForm factory 関数

クラスの定義を使用する代わりに、スタンドアロンの関数 [`modelform_factory()`](/ja/2.2/ref/forms/models/#django.forms.models.modelform_factory) を使って、与えられたモデルからフォームを生成することができます。作成時にカスタマイズをたくさん行わない場合に便利です:

```
>>> from django.forms import modelform_factory
>>> from myapp.models import Book
>>> BookForm = modelform_factory(Book, fields=("author", "title"))
```

これは、既存のフォームに対してシンプルな修正を加えたい場合にも使用できます。例えば、与えられたフィールドに対して使われるウィジェットを指定できます:

```
>>> from django.forms import Textarea
>>> Form = modelform_factory(Book, form=BookForm,
...                          widgets={"title": Textarea()})
```

含むフィールドは `fields` や `exclude` のキーワード引数、もしくは `ModelForm` 内部の `Meta` クラスの対応する属性を使って指定できます。`ModelForm` [使うフィールドを選択する](#modelforms-selecting-fields) ドキュメントを参照してください。

... もしくは、特定のフィールドに対してローカル化を有効にします:

```
>>> Form = modelform_factory(Author, form=AuthorForm, localized_fields=("birth_date",))
```

## モデルのフォームセット

#### `class models.BaseModelFormSet`

[通常のフォームセット](/ja/2.2/topics/forms/formsets/) のように、Django には Django モデルを簡単に扱うための拡張的なフォームセットのクラスが用意されています。前述の `Author` モデルを再利用して見ていきましょう:

```
>>> from django.forms import modelformset_factory
>>> from myapp.models import Author
>>> AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
```

`fields` を使用すると、フォームセットが与えられるフィールドだけを使うようになります。 もしくは、"オプトアウト" の方法 (除外するフィールドを指定する) を取ることもできます:

```
>>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))
```

以下は、`Author` モデルと連動するデータを扱うことができるフォームセットを作成します。これは通常のフォームセットと同じように動作します:

```
>>> formset = AuthorFormSet()
>>> print(formset)
<input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS"><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS"><input type="hidden" name="form-MAX_NUM_FORMS" id="id_form-MAX_NUM_FORMS">
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100"></td></tr>
<tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title">
<option value="" selected>---------</option>
<option value="MR">Mr.</option>
<option value="MRS">Mrs.</option>
<option value="MS">Ms.</option>
</select><input type="hidden" name="form-0-id" id="id_form-0-id"></td></tr>
```

> **Note**
>
> [`modelformset_factory()`](/ja/2.2/ref/forms/models/#django.forms.models.modelformset_factory) はフォームセットの生成に [`formset_factory()`](/ja/2.2/ref/forms/formsets/#django.forms.formsets.formset_factory) を使います。これは、モデルフォームが特定のモデルとやり取りする方法を知っている基本的なフォームセットの拡張だと言うことを意味します。

> **Note**
>
> When using [multi-table inheritance](/ja/2.2/topics/db/models/#multi-table-inheritance), forms
> generated by a formset factory will contain a parent link field (by default
> `<parent_model_name>_ptr`) instead of an `id` field.

### クエリセットを変更する

デフォルトでは、モデルからフォームセットを作成するときには、フォームセットはモデル内の全てのオブジェクトを含むクエリセット (例えば `Author.objects.all()`) を使用します。 `queryset` 属性を使うことで、この動作をオーバーライドできます:

```
>>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
```

もしくは、`__init__` の中で `self.queryset` をセットするサブクラスを作成できます:

```
from django.forms import BaseModelFormSet
from myapp.models import Author

class BaseAuthorFormSet(BaseModelFormSet):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.queryset = Author.objects.filter(name__startswith='O')
```

そして、`BaseAuthorFormSet` クラスを factory 関数に渡します:

```
>>> AuthorFormSet = modelformset_factory(
...     Author, fields=('name', 'title'), formset=BaseAuthorFormSet)
```

モデルの既存のインスタンスを *含まない* フォームセットを返したい場合は、空の QuerySet を指定できます:

```
>>> AuthorFormSet(queryset=Author.objects.none())
```

### フォームを変更する

By default, when you use `modelformset_factory`, a model form will
be created using [`modelform_factory()`](/ja/2.2/ref/forms/models/#django.forms.models.modelform_factory).
Often, it can be useful to specify a custom model form. For example,
you can create a custom model form that has custom validation:

```
class AuthorForm(forms.ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title')

    def clean_name(self):
        # custom validation for the name field
        ...
```

Then, pass your model form to the factory function:

```
AuthorFormSet = modelformset_factory(Author, form=AuthorForm)
```

It is not always necessary to define a custom model form. The
`modelformset_factory` function has several arguments which are
passed through to `modelform_factory`, which are described below.

### Specifying widgets to use in the form with `widgets`

Using the `widgets` parameter, you can specify a dictionary of values to
customize the `ModelForm`’s widget class for a particular field. This
works the same way as the `widgets` dictionary on the inner `Meta`
class of a `ModelForm` works:

```
>>> AuthorFormSet = modelformset_factory(
...     Author, fields=('name', 'title'),
...     widgets={'name': Textarea(attrs={'cols': 80, 'rows': 20})})
```

### Enabling localization for fields with `localized_fields`

Using the `localized_fields` parameter, you can enable localization for
fields in the form.

```
>>> AuthorFormSet = modelformset_factory(
...     Author, fields=('name', 'title', 'birth_date'),
...     localized_fields=('birth_date',))
```

`localized_fields` が特殊な値 `'__all__'` にセットされた場合、全てのフィールドがローカル化されます。

### Providing initial values

As with regular formsets, it's possible to [specify initial data](/ja/2.2/topics/forms/formsets/#formsets-initial-data) for forms in the formset by specifying an `initial`
parameter when instantiating the model formset class returned by
[`modelformset_factory()`](/ja/2.2/ref/forms/models/#django.forms.models.modelformset_factory). However, with model
formsets, the initial values only apply to extra forms, those that aren't
attached to an existing model instance. If the length of `initial` exceeds
the number of extra forms, the excess initial data is ignored. If the extra
forms with initial data aren't changed by the user, they won't be validated or
saved.

### Saving objects in the formset

As with a `ModelForm`, you can save the data as a model object. This is done
with the formset's `save()` method:

```python
# Create a formset instance with POST data.
>>> formset = AuthorFormSet(request.POST)

# Assuming all is valid, save the data.
>>> instances = formset.save()
```

The `save()` method returns the instances that have been saved to the
database. If a given instance's data didn't change in the bound data, the
instance won't be saved to the database and won't be included in the return
value (`instances`, in the above example).

When fields are missing from the form (for example because they have been
excluded), these fields will not be set by the `save()` method. You can find
more information about this restriction, which also holds for regular
`ModelForms`, in [Selecting the fields to use](#selecting-the-fields-to-use).

Pass `commit=False` to return the unsaved model instances:

```python
# don't save to the database
>>> instances = formset.save(commit=False)
>>> for instance in instances:
...     # do something with instance
...     instance.save()
```

This gives you the ability to attach data to the instances before saving them
to the database. If your formset contains a `ManyToManyField`, you'll also
need to call `formset.save_m2m()` to ensure the many-to-many relationships
are saved properly.

After calling `save()`, your model formset will have three new attributes
containing the formset's changes:

#### `models.BaseModelFormSet.changed_objects`

#### `models.BaseModelFormSet.deleted_objects`

#### `models.BaseModelFormSet.new_objects`

### Limiting the number of editable objects

As with regular formsets, you can use the `max_num` and `extra` parameters
to [`modelformset_factory()`](/ja/2.2/ref/forms/models/#django.forms.models.modelformset_factory) to limit the number of
extra forms displayed.

`max_num` does not prevent existing objects from being displayed:

```
>>> Author.objects.order_by('name')
<QuerySet [<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]>

>>> AuthorFormSet = modelformset_factory(Author, fields=('name',), max_num=1)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> [x.name for x in formset.get_queryset()]
['Charles Baudelaire', 'Paul Verlaine', 'Walt Whitman']
```

Also, `extra=0` doesn't prevent creation of new model instances as you can
[add additional forms with JavaScript](/ja/2.2/topics/forms/formsets/#understanding-the-managementform)
or just send additional POST data. Formsets [don't yet provide
functionality](https://code.djangoproject.com/ticket/26142) for an "edit only" view that prevents creation of new
instances.

If the value of `max_num` is greater than the number of existing related
objects, up to `extra` additional blank forms will be added to the formset,
so long as the total number of forms does not exceed `max_num`:

```
>>> AuthorFormSet = modelformset_factory(Author, fields=('name',), max_num=4, extra=2)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> for form in formset:
...     print(form.as_table())
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100"><input type="hidden" name="form-0-id" value="1" id="id_form-0-id"></td></tr>
<tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100"><input type="hidden" name="form-1-id" value="3" id="id_form-1-id"></td></tr>
<tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100"><input type="hidden" name="form-2-id" value="2" id="id_form-2-id"></td></tr>
<tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100"><input type="hidden" name="form-3-id" id="id_form-3-id"></td></tr>
```

`max_num` の値が `None` (デフォルト) だった場合、表示されるフォームの上限は大きな数になります (1000)。この数は、実際には制限がないと見なせるでしょう。

### Using a model formset in a view

Model formsets are very similar to formsets. Let's say we want to present a
formset to edit `Author` model instances:

```
from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Author

def manage_authors(request):
    AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
    if request.method == 'POST':
        formset = AuthorFormSet(request.POST, request.FILES)
        if formset.is_valid():
            formset.save()
            # do something.
    else:
        formset = AuthorFormSet()
    return render(request, 'manage_authors.html', {'formset': formset})
```

As you can see, the view logic of a model formset isn't drastically different
than that of a "normal" formset. The only difference is that we call
`formset.save()` to save the data into the database. (This was described
above, in [Saving objects in the formset](#saving-objects-in-the-formset).)

### Overriding `clean()` on a `ModelFormSet`

Just like with `ModelForms`, by default the `clean()` method of a
`ModelFormSet` will validate that none of the items in the formset violate
the unique constraints on your model (either `unique`, `unique_together` or
`unique_for_date|month|year`).  If you want to override the `clean()` method
on a `ModelFormSet` and maintain this validation, you must call the parent
class's `clean` method:

```
from django.forms import BaseModelFormSet

class MyModelFormSet(BaseModelFormSet):
    def clean(self):
        super().clean()
        # example custom validation across forms in the formset
        for form in self.forms:
            # your custom formset validation
            ...
```

Also note that by the time you reach this step, individual model instances
have already been created for each `Form`. Modifying a value in
`form.cleaned_data` is not sufficient to affect the saved value. If you wish
to modify a value in `ModelFormSet.clean()` you must modify
`form.instance`:

```
from django.forms import BaseModelFormSet

class MyModelFormSet(BaseModelFormSet):
    def clean(self):
        super().clean()

        for form in self.forms:
            name = form.cleaned_data['name'].upper()
            form.cleaned_data['name'] = name
            # update the instance value.
            form.instance.name = name
```

### Using a custom queryset

As stated earlier, you can override the default queryset used by the model
formset:

```
from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Author

def manage_authors(request):
    AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
    if request.method == "POST":
        formset = AuthorFormSet(
            request.POST, request.FILES,
            queryset=Author.objects.filter(name__startswith='O'),
        )
        if formset.is_valid():
            formset.save()
            # Do something.
    else:
        formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
    return render(request, 'manage_authors.html', {'formset': formset})
```

Note that we pass the `queryset` argument in both the `POST` and `GET`
cases in this example.

### Using the formset in the template

There are three ways to render a formset in a Django template.

First, you can let the formset do most of the work:

```html+django
<form method="post">
    {{ formset }}
</form>
```

Second, you can manually render the formset, but let the form deal with
itself:

```html+django
<form method="post">
    {{ formset.management_form }}
    {% for form in formset %}
        {{ form }}
    {% endfor %}
</form>
```

When you manually render the forms yourself, be sure to render the management
form as shown above. See the [management form documentation](/ja/2.2/topics/forms/formsets/#understanding-the-managementform).

Third, you can manually render each field:

```html+django
<form method="post">
    {{ formset.management_form }}
    {% for form in formset %}
        {% for field in form %}
            {{ field.label_tag }} {{ field }}
        {% endfor %}
    {% endfor %}
</form>
```

If you opt to use this third method and you don't iterate over the fields with
a `{% for %}` loop, you'll need to render the primary key field. For example,
if you were rendering the `name` and `age` fields of a model:

```html+django
<form method="post">
    {{ formset.management_form }}
    {% for form in formset %}
        {{ form.id }}
        <ul>
            <li>{{ form.name }}</li>
            <li>{{ form.age }}</li>
        </ul>
    {% endfor %}
</form>
```

Notice how we need to explicitly render `{{ form.id }}`. This ensures that
the model formset, in the `POST` case, will work correctly. (This example
assumes a primary key named `id`. If you've explicitly defined your own
primary key that isn't called `id`, make sure it gets rendered.)

## インラインフォームセット

#### `class models.BaseInlineFormSet`

インラインフォームセットは、モデルフォームセット上の小さな抽象化レイヤーです。これを使うと、外部キーで関連するオブジェクトを操作することが簡単になります。以下の 2 つのモデルがあるとします:

```python
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
```

ある作者 (Author) に紐付いた本 (Book) を編集するフォームセットを作成するには、以下のようにします:

```python
>>> from django.forms import inlineformset_factory
>>> BookFormSet = inlineformset_factory(Author, Book, fields=('title',))
>>> author = Author.objects.get(name='Mike Royko')
>>> formset = BookFormSet(instance=author)
```

`BookFormSet`'s [prefix](/ja/2.2/topics/forms/formsets/#formset-prefix) is `'book_set'`
(`<model name>_set` ). If `Book`'s `ForeignKey` to `Author` has a
[`related_name`](/ja/2.2/ref/models/fields/#django.db.models.ForeignKey.related_name), that's used instead.

> **Note**
>
> [`inlineformset_factory()`](/ja/2.2/ref/forms/models/#django.forms.models.inlineformset_factory) は、 [`modelformset_factory()`](/ja/2.2/ref/forms/models/#django.forms.models.modelformset_factory) を使い、`can_delete=True` をセットします。

> **See also**
>
> [手動でレンダリングされた can\_delete と can\_order](/ja/2.2/topics/forms/formsets/#manually-rendered-can-delete-and-can-order).

### `InlineFormSet` のメソッドをオーバーライドする

`InlineFormSet` のメソッドをオーバーライドするには、 [`BaseModelFormSet`](#django.forms.models.BaseModelFormSet) ではなく、 [`BaseInlineFormSet`](#django.forms.models.BaseInlineFormSet) をサブクラス化します。

例えば、 `clean()` をオーバーライドするとします:

```python
from django.forms import BaseInlineFormSet

class CustomInlineFormSet(BaseInlineFormSet):
    def clean(self):
        super().clean()
        # example custom validation across forms in the formset
        for form in self.forms:
            # your custom formset validation
            ...
```

[Overriding clean() on a ModelFormSet](#model-formsets-overriding-clean) も参照してください。

そして、インラインフォームセットを生成するとき、省略可能な引数の `formset` で渡します:

```python
>>> from django.forms import inlineformset_factory
>>> BookFormSet = inlineformset_factory(Author, Book, fields=('title',),
...     formset=CustomInlineFormSet)
>>> author = Author.objects.get(name='Mike Royko')
>>> formset = BookFormSet(instance=author)
```

### 複数の外部キーをひとつのモデルが持っている場合

同じモデルが 1 つよりも多くの外部キーを持っている場合、 `fk_name` を使い手動で曖昧さを解消しなければなりません。例として、次のモデルについて考えます:

```python
class Friendship(models.Model):
    from_friend = models.ForeignKey(
        Friend,
        on_delete=models.CASCADE,
        related_name='from_friends',
    )
    to_friend = models.ForeignKey(
        Friend,
        on_delete=models.CASCADE,
        related_name='friends',
    )
    length_in_months = models.IntegerField()
```

これを解決するには、  `fk_name` を  [`inlineformset_factory()`](/ja/2.2/ref/forms/models/#django.forms.models.inlineformset_factory) に使います:

```python
>>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name='from_friend',
...     fields=('to_friend', 'length_in_months'))
```

### ビューでインラインフォームセットを使う

モデルに紐付いたオブジェクトを編集する機能をユーザーに提供するビューを作るには、こうします:

```python
def manage_books(request, author_id):
    author = Author.objects.get(pk=author_id)
    BookInlineFormSet = inlineformset_factory(Author, Book, fields=('title',))
    if request.method == "POST":
        formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
        if formset.is_valid():
            formset.save()
            # Do something. Should generally end with a redirect. For example:
            return HttpResponseRedirect(author.get_absolute_url())
    else:
        formset = BookInlineFormSet(instance=author)
    return render(request, 'manage_books.html', {'formset': formset})
```

`POST` と `GET` いずれにおいても `instance` を渡していることに注目してください

### インラインフォームにウィジェットを指定する

`inlineformset_factory` は `modelformset_factory` を使っており、多くの引数は `modelformset_factory` に渡されます。これは `modelformset_factory` と同様に、 `widgets` 引数を渡すことができることを意味しています。詳細は、上記 [Specifying widgets to use in the form with widgets](#specifying-widgets-to-use-in-the-form-with-widgets) を参照してください。
