Django ModelForm: save (commit = False)用于什么?

我为什么要使用 save(commit=False)而不是仅仅从 ModelForm子类创建一个表单对象并运行 is_valid()来验证表单和模型呢?

In other words, what is save(commit=False) for?

如果你们不介意的话,你们能不能提供一些假设的情况,在这种情况下这可能是有用的?

92022 次浏览

来自姜戈的文件:

这个 save ()方法接受一个可选的 commit 关键字参数, 它接受 True 或 False。如果使用 commit=False调用 save () , 然后它将返回一个尚未保存到数据库的对象。

在这种情况下,您可以对生成的模型实例调用 save ()。 This is useful if you want to do custom processing on the object before saving it, 或者如果你想使用一个特殊的模型保存选项。 提交默认为 True。

Save (commit=False)似乎确实创建了一个模型实例,并将其返回给您。这是一些后期处理之前,实际上保存它整洁!

当您从表单获得大部分模型数据时,这非常有用,但是您需要用非表单数据填充一些 null=False字段。

使用 commit=False保存将获得一个模型对象,然后您可以添加额外的数据并保存它。

这就是一个很好的例子。

这是 保存方法的文档。注意,如果表单包含多对多字段,那么在保存模型实例之后还需要调用 form.save_m2m()

这就是答案(来自医生) :

# 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()

作为一个“真实的例子”,考虑一个电子邮件地址和用户名始终相同的用户模型,然后您可以覆盖您的 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将用户名设置为电子邮件地址,那么您要么必须修改用户模型的 save 方法,要么必须将用户对象保存两次(这将复制一个昂贵的数据库操作)

            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()

here is my example of using save(commit=False). I wanted to check what type of file a user uploaded before saving it to the database. I also wanted to get the date it was attached since that field was not in the form.

In simple words, here we update the form object and let them know that don't save the values in the database right now, we might change some input with instance and then use .save() to save all values in the database.

这使我们能够灵活地从 HTML 表单获取所有值,并根据我们的需求定制它们,然后保存实例。

我在这里理解的基本事情是,它在视图中从一个“表单”实例变为一个特定的“模型”实例。

假设我想在 StackOverflow 中发布这样的答案。 代码是这样的:

# 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在视图页面,也不在表单类。

所以基本上,它从“表单”实例变成了“模型”实例,然后允许您修改数据并保存它。