Django ModelForm: บันทึก (กระทำ = เท็จ) ใช้สำหรับอะไร?


90

เหตุใดฉันจึงใช้save(commit=False)แทนที่จะสร้างออบเจ็กต์ฟอร์มจากModelFormคลาสย่อยและเรียกใช้is_valid()เพื่อตรวจสอบความถูกต้องทั้งฟอร์มและโมเดล

กล่าวอีกนัยหนึ่งคือsave(commit=False)อะไร?

หากคุณไม่ทราบพวกคุณช่วยจัดเตรียมสถานการณ์สมมติที่อาจเป็นประโยชน์ได้หรือไม่?

คำตอบ:


111

ซึ่งมีประโยชน์เมื่อคุณได้รับข้อมูลโมเดลส่วนใหญ่จากฟอร์ม แต่จำเป็นต้องเติมnull=Falseข้อมูลบางฟิลด์ด้วยข้อมูลที่ไม่ใช่ฟอร์ม

การบันทึกด้วยการกระทำ = False ทำให้คุณได้รับโมเดลออบเจ็กต์จากนั้นคุณสามารถเพิ่มข้อมูลพิเศษของคุณและบันทึกได้

นี่เป็นตัวอย่างที่ดีของสถานการณ์นั้น


แต่ถ้าสิ่งนี้ทำให้คุณได้รับโมเดลอ็อบเจ็กต์มันจะแตกต่างจากการกำหนดอ็อบเจ็กต์อินสแตนซ์ก่อนหน้านี้และกำหนดให้กับ ModelForm อย่างไร (เช่นform = forms.SampleForm(instance = models.Sample))
OzzyTheGiant

คุณต้องการcommit=Falseถ้าคุณกำลังประมวลผลแบบฟอร์มของคุณCBVด้วยdef form_validหรือไม่? ใช้แค่form.instance.[field]อัพเดทได้ไหม?
นามแฝง 51

ไปที่ 100 :)
dani herrera

43

นี่คือคำตอบ ( จากเอกสาร ):

# 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ถ้าคุณกำลังประมวลผลแบบฟอร์มของคุณCBVด้วยdef form_validหรือไม่? ใช้แค่form.instance.[field]อัพเดทได้ไหม?
นามแฝง 51

15

จากเอกสาร Django:

เมธอด save () นี้ยอมรับอาร์กิวเมนต์คอมมิตคีย์เวิร์ดที่เป็นทางเลือกซึ่งยอมรับทั้ง True หรือ False ถ้าคุณเรียก save () ด้วยการกระทำ = False มันจะส่งคืนวัตถุที่ยังไม่ได้บันทึกลงในฐานข้อมูล

ในกรณีนี้ขึ้นอยู่กับคุณที่จะเรียก save () บนอินสแตนซ์โมเดลที่เป็นผลลัพธ์ สิ่งนี้มีประโยชน์หากคุณต้องการดำเนินการประมวลผลแบบกำหนดเองบนวัตถุก่อนบันทึกหรือหากคุณต้องการใช้ตัวเลือกการบันทึกโมเดลพิเศษ การกระทำเป็น True โดยค่าเริ่มต้น

ดูเหมือนว่าการบันทึก (กระทำ = False) จะสร้างอินสแตนซ์แบบจำลองซึ่งจะส่งคืนให้คุณ ซึ่งเรียบร้อยสำหรับการประมวลผลหลังการบันทึกจริง!


10

ในฐานะ "ตัวอย่างจริง" ให้พิจารณารูปแบบผู้ใช้ที่ที่อยู่อีเมลและชื่อผู้ใช้จะเหมือนกันเสมอจากนั้นคุณสามารถเขียนทับวิธีการบันทึกของ 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เพื่อตั้งชื่อผู้ใช้เป็นที่อยู่อีเมลคุณอาจต้องแก้ไขวิธีการบันทึกของโมเดลผู้ใช้หรือบันทึกออบเจ็กต์ผู้ใช้สองครั้ง (ซึ่งซ้ำกับการดำเนินการฐานข้อมูลที่มีราคาแพง)


คุณต้องการcommit=Falseถ้าคุณกำลังประมวลผลแบบฟอร์มของคุณCBVด้วยdef form_validหรือไม่? ใช้แค่form.instance.[field]อัพเดทได้ไหม?
นามแฝง 51

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

นี่คือตัวอย่างของฉันในการใช้บันทึก (กระทำ = เท็จ) ฉันต้องการตรวจสอบประเภทของไฟล์ที่ผู้ใช้อัปโหลดก่อนบันทึกลงในฐานข้อมูล ฉันยังต้องการรับวันที่แนบเนื่องจากช่องนั้นไม่อยู่ในแบบฟอร์ม


นี่คือรหัสหลามที่คุณไม่สามารถเรียกใช้ในข้อมูลโค้ดได้
Ayoub Benayache

0

พูดง่ายๆคือที่นี่เราอัปเดตวัตถุฟอร์มและแจ้งให้พวกเขาทราบว่าอย่าบันทึกค่าในฐานข้อมูลในตอนนี้เราอาจเปลี่ยนอินพุตบางส่วนด้วยอินสแตนซ์จากนั้นใช้. บันทึก () เพื่อบันทึกค่าทั้งหมดในฐานข้อมูล

สิ่งนี้ทำให้เรามีความยืดหยุ่นในการรับค่าทั้งหมดจากรูปแบบ HTML และปรับแต่งตามความต้องการของเราจากนั้นบันทึกอินสแตนซ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.