Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

ModelForm

Crazy丶土豆 2019-01-24 14:48:00 阅读数:263 评论数:0 点赞数:0 收藏数:0

 

ModelForm

模型的属性与表单属性对应关系

如果模型字段设置了 

blank=True ,那么表单字段的 

required 属性被设置为 

False,否则 

required=True 。

表单字段的 

label 设置为模型字段的 

verbose_name ,并且首字母大写。

表单字段的 

help_text 设置为模型字段的 

help_text 。

如果模型字段设置了 

choices ,那么表单字段的 

widget 会被设置为 

Select ,其选项来自模型字段的 

choices 。这些选项通常包含一个默认选中的空选项。如果字段设置了必填,则会强制用户进行选择。如果模型字段设置了 

blank=False 以及一个明确的 

default 值,则表单字段中不会包含空选项(默认会选中 

default 值)

error_messages注意事项

在 form field 级别或者 form Meta 级别定义的错误信息优先级总是高于在 model field 级别定义的。

在 model fields 上定义的错误信息只有在 model validation 步骤引发 

ValidationError 时才会使用,并且没有在表单级定义相应的错误信息。

您可以通过添加 

NONFIELDERRORS到 

ModelForm 内部的 

Meta 类的 

error_messages 中来覆盖模型验证引发的 

NONFIELDERRORS 错误信息

from django.core.exceptions importNONFIELDERRORSfrom django.forms importModelFormclassArticleForm(ModelForm):classMeta: errormessages={ NONFIELDERRORS: {'uniquetogether': "%(modelname)s's %(fieldlabels)s are not unique.", } }View Code

save()方法

每个 

ModelForm 还有一个 

save() 方法。此方法根据绑定到表单的数据创建并保存数据库对象。 

ModelForm 的子类可接受一个现有的模型实例作为关键字参数 

instance ;如果提供了,则 

save() 会更新这个实例。如果没有,则 

save() 会创建一个对应模型的新实例。

>> from myapp.models importArticle>>> from myapp.forms importArticleForm/#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()
View Code

请注意,如果表单尚未验证,调用 

save() 将通过检查 

form.errors 来实现验证。如果表单验证不过,则会引发 

ValueError —— 比如,如果 

form.errors 返回 

True 。

 

save() 方法接受一个可选参数 

commit ,它的值是 

True 或者 

False 。如果调用 

save()的时候使用 

commit=False ,那么它会返回一个尚未保存到数据库的对象。在这种情况下,需要您自己在生成的模型实例上调用 

save() 。如果要在保存对象之前对对象执行自定义操作,或者要使用其中一个专用的 model save options,这很有用。 

commit 的值默认为 

True。

另一个使用 

commit=False 的作用,您可以在模型与另一个模型有多对多关系的时候看到。如果您的模型具有多对多关系,并且在保存表单时指定了 

commit=False ,Django无法立即保存多对多关系的表单数据。这是因为实例的多对多数据只有实例在数据库中存在时才能保存。

要解决这个问题,Django会在您每次使用 

commit=False 保存表单时,向 

ModelForm 子类添加一个 

save_m2m() 方法。在您手动保存表单生成的实例后,可以调用 

save_m2m()来保存多对多的表单数据。例如:

/#用POST数据创建一个表单实例 >>> f =AuthorForm(request.POST)/#返回一个尚未保存的实例对象 >>> newauthor = f.save(commit=False)/#修改一些数据 >>> newauthor.somefield = 'somevalue' /#保存这个新的实例 >>>newauthor.save()/#调用savem2m(),保存具有 多对多关系 的数据 >>> f.save_m2m()View Code

只有在您使用 

save(commit=False) 的时候才需要调用 

save_m2m() 。当您在表单上使用普通的 

save() 时,无需调用其他方法,所有数据(包括多对多数据)都会被保存。例如:

/#用POST数据创建表单实例 >>> a =Author()>>> f = AuthorForm(request.POST, instance=a)/#创建并保存这个新实例,不需要在做其他事 >>> new_author = f.save()View Code

除了 

save() 和 

save_m2m() 方法之外,

ModelForm 与普通的表单工作方式一样。例如,用 

is_valid() 方法来检查合法性,用 

is_multipart() 方法来确定表单是否需要multipart文件上传(之后是否必须将 

request.FILES 传递给表单),等等。更多相关信息,请参阅 Binding uploaded files to a form 。

 

选择要使用的字段

强烈建议您使用 

fields 属性来显式设置所有应在表单中编辑的字段。如果不这样做,当一张表单不慎允许用户设置某些字段,尤其是在将新字段添加到模型中时,很容易导致安全问题。根据表单渲染方式的不同,甚至可能不会在网页上显示问题。

另一种方法是自动包含所有字段,其他放入黑名单。

但是,有两种简单的方法保证你不会出现这些安全问题:

1.将 

fields 属性设置为特殊值 

'all' 以表明需要使用模型中的所有字段。例如:

from django.forms importModelFormclassAuthorForm(ModelForm):classMeta: model=Author fields= 'all'View Code

  1. 将 

ModelForm 中Meta类的 

exclude 属性设置为表单中需要排除的字段列表。

例如:

classPartialAuthorForm(ModelForm):classMeta: model=Author/#除了"title"字段,其他字段都需要显示 exclude = ['title']View Code

不管使用哪一种,字段会按模型中定义的顺序在表单中出现, 

ManyToManyField 会排在最后。

另外,Django有个规则:如果您在模型字段中定义了 

editable=False , /*任何/*使用 

ModelForm 给该模型创建的表单都不会包含这个字段

注意: 任何没在上面逻辑中包含的表单字段都会不被表单的 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()View Code

 

覆盖默认字段

form和

model模型的默认字段类型都是相对应的。如果您的模型中有一个 

DateField ,您可能希望在表单中将它展示为 

DateField 。 

ModelForm 可以让您灵活地改变给定模型的表单字段

要为字段指定自定义组件,请使用内部 

Meta 类的 

widgets 属性。它可以是一个映射字段名到组件类或组件实例的字典。

例如,如果您希望 

Author 的 

name 属性的 

CharField 由