Django ModelForm:save(commit=False) 用于啥?
Posted
技术标签:
【中文标题】Django ModelForm:save(commit=False) 用于啥?【英文标题】:Django ModelForm: What is save(commit=False) used for?Django ModelForm:save(commit=False) 用于什么? 【发布时间】:2012-10-02 15:38:13 【问题描述】:为什么我会使用save(commit=False)
而不是仅仅从ModelForm
子类创建一个表单对象并运行is_valid()
来验证表单和模型?
换句话说,save(commit=False)
是干什么用的?
如果你不介意,你们能提供一些假设情况,这可能有用吗?
【问题讨论】:
【参考方案1】:来自 Django 文档:
这个 save() 方法接受一个可选的 commit 关键字参数, 它接受 True 或 False。如果您使用
commit=False
调用 save(), 那么它将返回一个尚未保存到数据库的对象。在这种情况下,您可以在生成的模型实例上调用 save()。 如果您想在保存对象之前对其进行自定义处理,这很有用, 或者,如果您想使用一种专门的模型保存选项。 commit 默认为 True。
看来 save(commit=False
) 确实创建了一个模型实例,它会返回给您。在实际保存之前进行一些后期处理是很整洁的!
【讨论】:
【参考方案2】:我理解的基本情况是它从“表单”实例变为视图中的特定“模型”实例。
假设我想在 *** 中发布这样的答案。 代码是这样的:
# Create a form instance with POST data.
>>> form_data = AnswerForm(request.POST)
# Create, but don't save the new answer instance.
>>> Answer = form_data.save(commit=False)
所以现在我们必须添加这个答案的所有者并将它保存在我们的数据库中的视图页面中,如下所示:
>>> Answer.owner = request.user
>>> Answer.save()
所以像这样,我们可以在视图页面中添加这个答案的所有者,我们不能像 form_data.owner = request.user
那样在表单类中添加。
所以基本上,它从“表单”实例变为“模型”实例,然后让您修改数据并保存。
【讨论】:
【参考方案3】:这在您从表单中获取大部分模型数据时很有用,但您需要使用非表单数据填充一些 null=False
字段。
使用commit=False
保存会得到一个模型对象,然后您可以添加额外的数据并保存它。
This is a good example of that situation.
【讨论】:
但是如果这给你一个模型对象,它与分配一个先前实例化的对象并将它分配给 ModelForm 有什么不同呢? (即form = forms.SampleForm(instance = models.Sample)
)
如果您在CBV
和def form_valid
中处理表单,是否需要commit=False
?可以直接用form.instance.[field]
更新吗?
我们去100 :)【参考方案4】:
简单来说,这里我们更新表单对象并让他们知道现在不要将值保存在数据库中,我们可能会使用实例更改一些输入,然后使用 .save() 将所有值保存在数据库。
这使我们可以灵活地从 html 表单中获取所有值并根据我们的要求对其进行自定义,然后保存实例。
【讨论】:
【参考方案5】: form = AddAttachmentForm(request.POST, request.FILES)
if form.is_valid():
attachment = form.save(commit=False)
attachment.user = student
attachment.attacher = self.request.user
attachment.date_attached = timezone.now()
attachment.competency = competency
attachment.filename = request.FILES['attachment'].name
if attachment.filename.lower().endswith(('.png','jpg','jpeg','.ai','.bmp','.gif','.ico','.psd','.svg','.tiff','.tif')):
attachment.file_type = "image"
if attachment.filename.lower().endswith(('.mp4','.mov','.3g2','.avi','.flv','.h264','.m4v','.mpg','.mpeg','.wmv')):
attachment.file_type = "video"
if attachment.filename.lower().endswith(('.aif','.cda','.mid','.midi','.mp3','.mpa','.ogg','.wav','.wma','.wpl')):
attachment.file_type = "audio"
if attachment.filename.lower().endswith(('.csv','.dif','.ods','.xls','.tsv','.dat','.db','.xml','.xlsx','.xlr')):
attachment.file_type = "spreasheet"
if attachment.filename.lower().endswith(('.doc','.pdf','.rtf','.txt')):
attachment.file_type = "text"
attachment.save()
这是我使用 save(commit=False) 的示例。我想在将其保存到数据库之前检查用户上传的文件类型。我还想获取它的附加日期,因为该字段不在表单中。
【讨论】:
这是一个python代码,你不能在代码sn-p中运行它【参考方案6】:作为“真实示例”,考虑一个用户模型,其中电子邮件地址和用户名始终相同,然后您可以覆盖 ModelForm 的保存方法,例如:
class UserForm(forms.ModelForm):
...
def save(self):
# Sets username to email before saving
user = super(UserForm, self).save(commit=False)
user.username = user.email
user.save()
return user
如果您没有使用commit=False
将用户名设置为电子邮件地址,您要么必须修改用户模型的保存方法,要么将用户对象保存两次(这会重复昂贵的数据库操作。)
【讨论】:
如果您在CBV
和def form_valid
中处理表单,是否需要commit=False
?可以直接用form.instance.[field]
更新吗?【参考方案7】:
这就是答案(from docs):
# 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()
【讨论】:
如果您在CBV
和def form_valid
中处理表单,是否需要commit=False
?可以直接用form.instance.[field]
更新吗?以上是关于Django ModelForm:save(commit=False) 用于啥?的主要内容,如果未能解决你的问题,请参考以下文章
使用覆盖保存为抽象模型扩展 Django ModelForm