Django ModelForm:save(commit = False)は何に使用されますか?


88

サブクラスsave(commit=False)からフォームオブジェクトを作成してModelForm実行する代わりにis_valid()、フォームとモデルの両方を検証するために使用するのはなぜですか?

言い換えれば、何のsave(commit=False)ためですか?

よろしければ、これが役立つと思われる架空の状況を提供していただけませんか。

回答:


110

これは、ほとんどのモデルデータをフォームから取得するが、一部のnull=Falseフィールドにフォーム以外のデータを入力する必要がある場合に役立ちます。

commit = Falseで保存すると、モデルオブジェクトが取得されます。その後、データを追加して保存できます。

これはその状況の良い例です。


しかし、これでモデルオブジェクトが得られた場合、以前にインスタンス化されたオブジェクトを割り当ててModelFormに割り当てるのとどう違うのでしょうか。(つまりform = forms.SampleForm(instance = models.Sample)
OzzyTheGiant

あなたが必要ですcommit=Falseあなたがあなたのフォームを処理する場合CBVdef form_validform.instance.[field]更新に使用できますか?
alias51

100に行きましょう:)
ダニエレーラ

39

ここに答えがあります(ドキュメントから):

# 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あなたがあなたのフォームを処理する場合CBVdef form_validform.instance.[field]更新に使用できますか?
alias51

14

Djangoのドキュメントから:

このsave()メソッドは、TrueまたはFalseのいずれかを受け入れるオプションのcommitキーワード引数を受け入れます。commit = Falseを指定してsave()を呼び出すと、データベースにまだ保存されていないオブジェクトが返されます。

この場合、結果のモデルインスタンスでsave()を呼び出すのはあなた次第です。これは、オブジェクトを保存する前にカスタム処理を実行する場合、または特殊なモデル保存オプションの1つを使用する場合に役立ちます。コミットはデフォルトで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メソッドを変更するか、ユーザーオブジェクトを2回保存する必要があります(これは高価なデータベース操作を複製します)。


あなたが必要ですcommit=Falseあなたがあなたのフォームを処理する場合CBVdef form_validform.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コードです
AyoubBenayache19年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.