フォームは、リクエストから POST データを取得するプロセス (の開発) を簡素化および高速化するための単なるツールです。手動の方法はrequest.POST.get('somefield')
、HTML フォームにあるすべてのフィールドに対して行うことです。しかし、Django はそれよりもうまくやることができます...
本質的に、フォーム クラスは多数のフィールドを保持し、次のタスクを実行します。
- HTML 入力の表示、
- ユーザーがデータを送信したときにデータを収集して検証する
- フィールドが検証されない場合は、エラー メッセージとともに値を HTML に返します。
- すべてのフィールドが有効
form.cleaned_data
な場合は、ビュー内のこれらの値にアクセスするための便利な方法としてディクショナリを提供します。
これらの値を使用して、a の新しいインスタンスを手動で作成し、MyModel
保存することができます。もちろん、MyModel モデルのすべての Field に対して Form で Field を定義する必要があります。
これは、基本的に、次のようなことができることを意味します:
(このコードをテストしていないことを許してください。100% 正しいとは保証できません)
models.py:
class MyModel(models.Model):
field1 = models.CharField(max_length=40, blank=False, null=False)
field2 = models.CharField(max_length=60, blank=True, null=True)
forms.py:
class FormForMyModel(forms.Form):
form_field1 = forms.CharField(max_length=40, required=True)
form_field2 = forms.CharField(max_length=60, required=False)
views.py:
def create_a_my_model(request):
if request.method == 'POST':
form = FormForMyModel(request.POST)
if form.is_valid():
my_model = MyModel()
my_model.field1 = form.cleaned_data.get('form_field1', 'default1')
my_model.field2 = form.cleaned_data.get('form_field2', 'default2')
my_model.save()
else:
form = FormForMyModel()
context_data = {'form': form}
return HttpResponse('templtate.html', context_data)
(これは数行少ないコードで記述できますが、可能な限り明確にすることを目的としています)
モデル フィールドとフォーム フィールドの間には関係がないことに注意してください。作成時に MyModel インスタンスに手動で値を割り当てる必要があります。
上記の例は、一般的なフォーム ワークフローの概要を示しています。複雑な状況で必要になることがよくありますが、この例のような単純な状況では必要ありません。
この例 (および実世界の多くの例) では、Django はそれよりも優れた処理を実行できます...
上記の例で 2 つの厄介な問題に気付くことができます。
MyModel
Fields onと Fields on をFormForMyModel
別々に定義する必要があります。ただし、フィールドのこれら 2 つのグループ (タイプ) には多くの類似点があるため、重複作業のようなものです。ラベル、バリデーターなどを追加すると、類似性が高まります。
- インスタンスの作成は
MyModel
少しばかげており、これらすべての値を手動で割り当てる必要があります。
ここでModelFormの出番です。
これらは基本的に通常のフォームと同じように機能します (実際には、通常のフォームから拡張されています) が、作業の一部を節約できます (もちろん、今概説した 2 つの問題:))。
では、2 つの問題に戻ります。
モデル フィールドごとにフォーム フィールドを定義する代わりにmodel = MyModel
、Meta
クラスで定義するだけです。これは、モデル フィールドからフォーム フィールドを自動的に生成するようにフォームに指示します。
モデルフォームにはsave
利用可能なメソッドがあります。これを使用して、フィールドごとに手動で割り当てる代わりに、ビュー内の 1 行でモデルのインスタンスを作成できます。
それでは、上記の例をModelForm
:
models.py:
class MyModel(models.Model):
field1 = models.CharField(max_length=40, blank=False, null=False)
field2 = models.CharField(max_length=60, blank=True, null=True)
forms.py:
class MyModelForm(forms.ModelForm): # extending ModelForm, not Form as before
class Meta:
model = MyModel
views.py:
def create_a_my_model(request):
if request.method == 'POST':
form = MyModelForm(request.POST)
if form.is_valid():
# save the model to database, directly from the form:
my_model = form.save() # reference to my_model is often not needed at all, a simple form.save() is ok
# alternatively:
# my_model = form.save(commit=False) # create model, but don't save to database
# my.model.something = whatever # if I need to do something before saving it
# my.model.save()
else:
form = MyModelForm()
context_data = {'form': form}
return HttpResponse('templtate.html', context_data)
これにより、Django フォームの使用法が少し明確になることを願っています。
もう 1 つ注意してくださいModelForm
。これらは使用されませんが、通常のフォームと同じようにform.save()
アクセスできます。form.cleaned_data