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


88

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

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

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

Answers:


110

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

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

这是这种情况的一个很好的例子。


但是,如果这为您提供了一个模型对象,那么它与分配先前实例化的对象并将其分配给ModelForm有何不同?(即form = forms.SampleForm(instance = models.Sample)
OzzyTheGiant

commit=False如果要使用CBVwith处理表格,是否需要def form_valid?您可以使用form.instance.[field]更新吗?
alias51

让我们去100 :)
丹妮·埃雷拉

39

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

1
commit=False如果要使用CBVwith处理表格,是否需要def form_valid?您可以使用form.instance.[field]更新吗?
alias51

14

从Django文档中:

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

在这种情况下,由您决定在结果模型实例上调用save()。如果要在保存之前对对象进行自定义处理,或者要使用一种特殊的模型保存选项,此功能将非常有用。默认情况下,commit为True。

似乎save(commit = False)确实创建了一个模型实例,然后返回给您。在实际保存之前,对于某些后期处理而言,这很不错!


10

作为“真实示例”,考虑一个用户模型,其中电子邮件地址和用户名始终相同,然后您可以覆盖ModelForm的save方法,例如:

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方法,要么将用户对象保存两次(这将重复昂贵的数据库操作)。


commit=False如果要使用CBVwith处理表格,是否需要def form_valid?您可以使用form.instance.[field]更新吗?
alias51

1
            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代码,您无法在代码段中运行它
Ayoub Benayache
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.