表单只是一种工具,用于简化和加速(开发)从请求中获取 POST 数据的过程。一种手动方法是request.POST.get('somefield')
对某些 HTML 表单中的所有字段进行处理。但是 Django 可以做得更好……
从本质上讲,Form 类包含许多字段并执行以下任务:
- 显示 HTML 输入,
- 在用户提交数据时收集和验证数据,
- 如果字段未验证,则将值与错误消息一起返回到 HTML,
- 如果所有字段都有效,则提供
form.cleaned_data
字典作为访问视图中这些值的便捷方式。
使用这些值,我可以手动创建 a 的新实例MyModel
并保存它。当然,我必须在表单中为 MyModel 模型中的每个字段定义一个字段。
这意味着,基本上,我可以做这样的事情:(请
原谅我没有测试这段代码,所以我不能保证它是 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 可以做得比这更好......
您可以在上面的示例中注意到两个烦人的问题:
- 我必须分别定义 Fields on
MyModel
和 Fields on FormForMyModel
。然而,这两组(类型)的字段之间有很多相似之处,所以这是一种重复的工作。添加标签、验证器等时,相似性会增加。
- 创建
MyModel
实例有点傻,必须手动分配所有这些值。
这就是ModelForm的用武之地。
这些行为基本上就像一个常规形式(实际上,它们是从常规形式扩展而来的),但它们可以为我节省一些工作(当然是我刚刚概述的两个问题 :))。
那么回到两个问题:
我没有为每个模型字段定义一个表单字段,而是简单地model = MyModel
在Meta
类中定义。这指示表单从模型字段自动生成表单字段。
模型表格有save
可用的方法。这可用于在视图中的一行中创建模型实例,而不是逐个字段手动分配。
所以,让我们用一个来做上面的例子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 表单的使用。
还有一点需要注意 - 在ModelForm
. 这些将不会被使用,form.save()
但仍然可以form.cleaned_data
像在常规表单中一样访问。