Django ModelForm: Untuk apa simpan (commit = False) digunakan?

90

Mengapa saya pernah menggunakan save(commit=False)alih-alih hanya membuat objek formulir dari ModelFormsubkelas dan menjalankan is_valid()untuk memvalidasi formulir dan model?

Dengan kata lain, untuk apa save(commit=False)?

Jika Anda tidak keberatan, dapatkah Anda memberikan situasi hipotetis yang mungkin berguna?

sgarza62
sumber

Jawaban:

111

Itu berguna saat Anda mendapatkan sebagian besar data model Anda dari formulir, tetapi perlu mengisi beberapa null=Falsebidang dengan data non-formulir.

Menyimpan dengan commit = False memberi Anda objek model, lalu Anda dapat menambahkan data ekstra dan menyimpannya.

Ini adalah contoh bagus dari situasi itu.

dokkaebi
sumber
Tetapi kemudian jika ini memberi Anda objek model, apa bedanya dengan menetapkan objek yang dibuat sebelumnya dan menetapkannya ke ModelForm? (Yaitu form = forms.SampleForm(instance = models.Sample))
OzzyTheGiant
Apakah Anda perlu commit=Falsejika Anda memproses formulir Anda CBVdengan def form_valid? Bisakah Anda menggunakan form.instance.[field]untuk memperbarui?
alias51
Ayo pergi ke 100 :)
dani herrera
43

Ini jawabannya ( dari dokumen ):

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

Situasi paling umum adalah mendapatkan instance dari formulir tetapi hanya 'dalam memori', bukan dalam database. Sebelum menyimpannya, Anda ingin membuat beberapa perubahan:

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()
dani herrera
sumber
1
Apakah Anda perlu commit=Falsejika Anda memproses formulir Anda CBVdengan def form_valid? Bisakah Anda menggunakan form.instance.[field]untuk memperbarui?
alias51
15

Dari dokumen Django:

Metode save () ini menerima argumen kata kunci komit opsional, yang menerima True atau False. Jika Anda memanggil save () dengan commit = False, maka itu akan mengembalikan objek yang belum disimpan ke database.

Dalam kasus ini, terserah Anda untuk memanggil save () pada contoh model yang dihasilkan. Ini berguna jika Anda ingin melakukan pemrosesan kustom pada objek sebelum menyimpannya, atau jika Anda ingin menggunakan salah satu opsi penyimpanan model khusus. komit adalah Benar secara default.

Tampaknya save (commit = False) memang membuat instance model, yang dikembalikannya kepada Anda. Yang rapi untuk beberapa pemrosesan pos sebelum benar-benar menyimpannya!

AJRouvoet
sumber
10

Sebagai "contoh nyata", pertimbangkan model pengguna di mana alamat email dan nama pengguna selalu sama, lalu Anda dapat menimpa metode penyimpanan ModelForm Anda seperti:

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

Jika Anda tidak menggunakan commit=Falseuntuk menyetel nama pengguna ke alamat email, Anda harus mengubah metode penyimpanan model pengguna, atau menyimpan objek pengguna dua kali (yang menduplikasi operasi database yang mahal.)

Mark Chackerian
sumber
Apakah Anda perlu commit=Falsejika Anda memproses formulir Anda CBVdengan def form_valid? Bisakah Anda menggunakan form.instance.[field]untuk memperbarui?
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()

berikut adalah contoh saya menggunakan save (commit = False). Saya ingin memeriksa jenis file apa yang diunggah pengguna sebelum menyimpannya ke database. Saya juga ingin mendapatkan tanggal itu dilampirkan karena bidang itu tidak ada di formulir.

Kollyn Lund
sumber
ini adalah kode python Anda tidak dapat menjalankannya dalam potongan kode
Ayoub Benayache
0

Dengan kata sederhana, di sini kita memperbarui objek formulir dan memberi tahu mereka bahwa tidak menyimpan nilai dalam database sekarang, kita mungkin mengubah beberapa masukan dengan instance dan kemudian menggunakan .save () untuk menyimpan semua nilai dalam database.

Ini memberi kami fleksibilitas untuk mendapatkan semua nilai dari formulir HTML dan menyesuaikannya sesuai dengan kebutuhan kami dan kemudian menyimpan instance.

Shubham Sarda
sumber