สัญญาณ Django เทียบกับวิธีการบันทึกที่ลบล้าง


89

ฉันมีปัญหาในการคาดเดาสิ่งนี้ ตอนนี้ฉันมีโมเดลที่มีลักษณะเช่นนี้:

 def Review(models.Model)
    ...fields...
    overall_score = models.FloatField(blank=True)

def Score(models.Model)
    review = models.ForeignKey(Review)
    question = models.TextField()
    grade = models.IntegerField()

การตรวจสอบมี "คะแนน" หลายแบบโดย overall_score คือค่าเฉลี่ยของคะแนน เมื่อมีการบันทึกบทวิจารณ์หรือคะแนนฉันจำเป็นต้องคำนวณค่าเฉลี่ย Overall_score ใหม่ ตอนนี้ฉันใช้วิธีบันทึกที่ถูกลบล้าง การใช้เครื่องส่งสัญญาณของ Django จะมีประโยชน์หรือไม่?

คำตอบ:


85

โดยทั่วไปสัญญาณบันทึก / ลบเป็นสิ่งที่ดีในสถานการณ์ที่คุณจำเป็นต้องทำการเปลี่ยนแปลงซึ่งไม่เฉพาะเจาะจงกับรุ่นที่เป็นปัญหาหรืออาจใช้กับโมเดลที่มีบางอย่างเหมือนกันหรืออาจกำหนดค่าเพื่อใช้กับโมเดลต่างๆ

งานทั่วไปอย่างหนึ่งในsaveวิธีการที่ถูกลบล้างคือการสร้างทากโดยอัตโนมัติจากช่องข้อความบางส่วนในโมเดล นั่นคือตัวอย่างของบางสิ่งที่หากคุณต้องการนำไปใช้กับรุ่นต่างๆจะได้รับประโยชน์จากการใช้pre_saveสัญญาณโดยที่ตัวจัดการสัญญาณสามารถใช้ชื่อของฟิลด์กระสุนและชื่อของฟิลด์เพื่อสร้างกระสุนได้ เมื่อคุณมีสิ่งที่ต้องการแล้วฟังก์ชันการทำงานขั้นสูงใด ๆ ที่คุณวางไว้จะนำไปใช้กับทุกรุ่นเช่นการค้นหากระสุนที่คุณกำลังจะเพิ่มสำหรับประเภทของโมเดลที่เป็นปัญหาเพื่อให้แน่ใจว่ามีเอกลักษณ์

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

ตัวอย่างเช่นด้วยdjango-mpttฉันใช้pre_saveสัญญาณเพื่อจัดการชุดของเขตข้อมูลซึ่งอธิบายโครงสร้างต้นไม้สำหรับโมเดลที่กำลังจะสร้างหรืออัปเดตและpre_deleteสัญญาณเพื่อลบรายละเอียดโครงสร้างต้นไม้สำหรับวัตถุที่ถูกลบและทั้งหมด โครงสร้างย่อยของวัตถุก่อนหน้านั้นและจะถูกลบ เนื่องจากการใช้สัญญาณผู้ใช้ไม่จำเป็นต้องเพิ่มหรือแก้ไขsaveหรือdeleteวิธีการในแบบจำลองเพื่อให้การจัดการนี้เสร็จสิ้นพวกเขาเพียงแค่แจ้งให้ django-mptt ทราบว่าต้องการให้จัดการโมเดลใด


จะเกิดอะไรขึ้นถ้าเครื่องจัดการสัญญาณเรียกใช้ข้อยกเว้น ฉันคิดว่าพวกเขาไม่ควรเรียกใช้ข้อยกเว้นมิฉะนั้นก็ไม่เหมาะสม ฉันผิดเหรอ?
x-yuri

20

คุณถาม:

การใช้เครื่องส่งสัญญาณของ Django จะมีประโยชน์หรือไม่?

ฉันพบสิ่งนี้ใน django docs:

วิธีการแบบจำลองที่ถูกแทนที่จะไม่ถูกเรียกในการดำเนินการจำนวนมาก

โปรดทราบว่าไม่จำเป็นต้องเรียกเมธอด delete () สำหรับอ็อบเจ็กต์เมื่อลบอ็อบเจ็กต์จำนวนมากโดยใช้ QuerySet หรือเป็นผลมาจากการลบแบบเรียงซ้อน เพื่อให้แน่ใจว่าตรรกะการลบที่กำหนดเองได้รับการดำเนินการคุณสามารถใช้สัญญาณ pre_delete และ / หรือ post_delete

น่าเสียดายที่ไม่มีวิธีแก้ปัญหาเมื่อสร้างหรืออัปเดตออบเจ็กต์จำนวนมากเนื่องจากไม่มีการเรียกใช้ save (), pre_save และ post_save

จาก: การลบล้างวิธีโมเดลที่กำหนดไว้ล่วงหน้า


3
มุมมองรายการผู้ดูแลระบบ Django ใช้การลบจำนวนมาก ... สับสนจนกระทั่งเจอเรื่องไม่เป็นระเบียบนี้
N.Balauro

8
นอกจากนี้ยังระบุว่า "น่าเสียดายที่ไม่มีวิธีแก้ปัญหาในการสร้างหรืออัปเดตวัตถุจำนวนมากเนื่องจากไม่มีการเรียก save (), pre_save และ post_save" - ดังนั้นฉันไม่คิดว่านี่เป็นการแลกเปลี่ยนระหว่างวิธีการเหล่านี้
Cory

สิ่งนี้ใช้ได้กับทั้งสองวิธีดังนั้นคำตอบคือ: "ไม่ไม่มีประโยชน์ที่จะใช้สัญญาณแทนการลบล้างsaveวิธีการ"?
ม์

3

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



1

เพิ่มเติมเล็กน้อยจากเอกสาร Django เกี่ยวกับการลบจำนวนมาก ( .delete()วิธีการบนQuerySetวัตถุ):

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

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

และการอัปเดตจำนวนมาก ( .update()วิธีการบนQuerySetวัตถุ):

สุดท้ายโปรดทราบว่า update () ทำการอัปเดตที่ระดับ SQL ดังนั้นจึงไม่เรียกเมธอด save () ใด ๆ บนโมเดลของคุณและไม่ปล่อยสัญญาณ pre_save หรือ post_save (ซึ่งเป็นผลมาจากการเรียก Model.save ( )). หากคุณต้องการอัปเดตกลุ่มระเบียนสำหรับโมเดลที่มีเมธอด save () แบบกำหนดเองให้วนซ้ำและเรียกใช้ save ()

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update


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