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

时间:2012-10-11 21:12:36

标签: django django-models django-forms

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

换句话说,save(commit=False)是什么?

如果你不介意,你们可以提供假设的情况,这可能有用吗?

7 个答案:

答案 0 :(得分:73)

当您从表单中获取大部分模型数据时,这很有用,但需要使用非表单数据填充某些null=False字段。

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

This is a good example of that situation.

答案 1 :(得分:28)

这是答案(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()

答案 2 :(得分:9)

来自Django文档:

  

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

     

在这种情况下,您可以在生成的模型实例上调用save()。   如果要在保存对象之前对对象执行自定义处理,这非常有用,   或者如果您想使用其中一个专门的模型保存选项。   默认情况下,commit为True。

似乎save(commit = False)确实创建了一个模型实例,它返回给你。在实际保存之前,对于某些后期处理来说这很简洁!

答案 3 :(得分:7)

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

答案 4 :(得分:0)

            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)的示例。我想检查用户上传的文件类型,然后再将其保存到数据库中。我还想获取它的附加日期,因为该字段不在表格中。

答案 5 :(得分:0)

简单来说,我们在这里更新表单对象,并让他们知道现在不将值保存在数据库中,我们可以使用实例更改某些输入,然后使用.save()将所有值保存在数据库中。数据库。

这使我们可以灵活地从HTML表单中获取所有值并根据我们的要求自定义它们,然后保存实例。

答案 6 :(得分:0)

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

假设我想在堆栈溢出中发布这样的答案。 代码应该是这样的

# 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”这样的所有者,也不能在表单类中添加

所以基本上,它从'form'实例更改为'model'实例,然后让您修改数据并保存