post_save ใน django เพื่ออัปเดตอินสแตนซ์ทันที

ฉันกำลังพยายามอัปเดตบันทึกทันทีหลังจากบันทึกแล้ว ตัวอย่างนี้อาจดูเหมือนไม่มีจุดหมาย แต่ลองจินตนาการว่าเราจำเป็นต้องใช้ API หลังจากบันทึกข้อมูลแล้วเพื่อรับข้อมูลเพิ่มเติมและอัปเดตบันทึก:

def my_handler(sender, instance=False, **kwargs):
    t = Test.objects.filter(id=instance.id)
    t.blah = 'hello'
    t.save()

class Test(models.Model):
    title = models.CharField('title', max_length=200)
    blah = models.CharField('blah', max_length=200)

post_save.connect(my_handler, sender=Test)

ดังนั้นควรตั้งค่าฟิลด์ 'พิเศษ' เป็น 'สวัสดี' หลังจากบันทึกแต่ละครั้ง ถูกต้อง? แต่มันไม่ทำงาน

มีความคิดอะไรบ้าง?


person givp    schedule 28.10.2009    source แหล่งที่มา
comment
บางทีคุณอาจอธิบายว่ามันใช้งานไม่ได้อย่างไร ในตอนแรกหน้าแดงดูเหมือนว่าจะสร้างการวนซ้ำไม่สิ้นสุดเนื่องจากการเรียก post_save บันทึก ซึ่งควรเรียกใช้ post_save เป็นต้น บางที Django อาจป้องกันการเรียกซ้ำหรือไม่   -  person Ned Batchelder    schedule 29.10.2009
comment
ฉันเห็นวงวนไม่สิ้นสุดตรงนั้น หลังจากที่ t.save() ส่งสัญญาณ post_save ไปแล้ว ให้เดาว่าฟังก์ชันใดจะถูกเรียกใช้...   -  person stefanw    schedule 29.10.2009
comment
โอ้ ฉันรู้สึกว่า Django จะไม่ปล่อยให้การบันทึกครั้งที่สองทริกเกอร์ post_save อีกครั้งใช่ไหม ฉันเดาว่าไม่. ในกรณีนี้คุณพูดถูก มันจะเป็นวงวนไม่สิ้นสุด แต่ฉันไม่เห็นการวนซ้ำหรืออะไรเลย   -  person givp    schedule 29.10.2009
comment
นี่อาจเป็นคำถามโง่ๆ แต่คุณไม่สามารถทำการเรียก API ก่อนแล้วจึงบันทึกได้   -  person Matt Baker    schedule 29.10.2009
comment
คุณหมายถึงใช้ pre_save เหรอ? ฉันต้องทำในระดับโมเดลเพราะฉันไม่สามารถแก้ไขผู้ดูแลระบบ Django ได้ แต่อย่างใดสำหรับโปรเจ็กต์นี้   -  person givp    schedule 29.10.2009
comment
ทำไมคุณไม่อัปเดตวิธีการ save ให้ทำ ; self.blah= 'hello'; super( Test, self ).save( *args, **kw ) เกิดอะไรขึ้นกับการแทนที่ save()   -  person S.Lott    schedule 29.10.2009
comment
หากคุณกำลังเปลี่ยนรหัสใหม่ .update() แทนที่จะเป็น save() เพื่อหลีกเลี่ยงการวนซ้ำ เนื่องจาก update() ไม่ได้เรียกสัญญาณ post_save   -  person Brandon Bertelsen    schedule 26.02.2013


คำตอบ (2)


เมื่อคุณพบว่าตัวเองใช้สัญญาณ post_save เพื่ออัปเดตอ็อบเจ็กต์ของคลาสผู้ส่ง มีโอกาสที่คุณควรจะแทนที่วิธีบันทึกแทน ในกรณีของคุณ คำจำกัดความของโมเดลจะมีลักษณะดังนี้:

class Test(models.Model):
    title = models.CharField('title', max_length=200)
    blah = models.CharField('blah', max_length=200)

    def save(self, force_insert=False, force_update=False):
        if not self.blah:
            self.blah = 'hello'
        super(Test, self).save(force_insert, force_update)
person ozan    schedule 29.10.2009
comment
หากเขาทำสิ่งนี้กับโมเดลผู้ดูแลระบบ post_save จะเป็นทางออกที่ดีกว่าการแบ่งคลาสย่อยโมเดลผู้ดูแลระบบที่มีอยู่และแทนที่การบันทึก - person Paul McMillan; 29.10.2009
comment
จำเป็นต้องใช้ using=False ในรายการอาร์กิวเมนต์ของเมธอด 'บันทึก' ใน Django 1.3 และสูงกว่า - person eviltnan; 20.07.2012
comment
การแทนที่วิธีการบันทึกนั้นไม่เหมาะสมเสมอไปเนื่องจากเราไม่มีคีย์หลักจนกว่าเราจะเรียกบันทึก ดังนั้น หากคุณต้องการทำงานกับ PK ของอินสแตนซ์ มีเพียงตัวเลือกเดียวเท่านั้นที่น่าจะเป็น post_save - person chhantyal; 27.03.2015
comment
วิธีที่พิสูจน์ได้ในอนาคตในการแทนที่วิธี save ในขณะที่รวมอาร์กิวเมนต์ที่จำเป็นทั้งหมดคือ: def save(self, *args, **kwargs): - person yndolok; 21.04.2015

ตัวจัดการ post_save ไม่ใช้อินสแตนซ์ใช่ไหม ทำไมคุณถึงใช้มันกรอง? ทำไมไม่เพียงแค่ทำ:

def my_handler(sender, instance=False, created, **kwargs):
  if created:
     instance.blah = 'hello'
     instance.save()

รหัสที่มีอยู่ของคุณใช้งานไม่ได้เพราะมันวนซ้ำ และ Test.objects.filter(id=instance.id) ส่งคืนชุดแบบสอบถาม ไม่ใช่วัตถุ หากต้องการรับวัตถุเดี่ยวโดยตรง ให้ใช้ Queryset.get() แต่คุณไม่จำเป็นต้องทำอย่างนั้นที่นี่ อาร์กิวเมนต์ที่สร้างขึ้นป้องกันไม่ให้วนซ้ำ เนื่องจากจะตั้งค่าในครั้งแรกเท่านั้น

โดยทั่วไป เว้นแต่คุณจะต้องใช้สัญญาณ post_save จริงๆ คุณควรจะแทนที่เมธอด save() ของอ็อบเจ็กต์ของคุณอยู่ดี

person Paul McMillan    schedule 28.10.2009
comment
จริงๆ แล้วฉันพยายามทำแบบนั้นแต่ก็ไม่ได้ผล แต่ถ้าคนข้างบนถูกต้อง ฉันก็ทำไม่ได้อยู่แล้วเพราะมันจะติดอยู่ในลูป post_save - person givp; 29.10.2009
comment
ลองใช้แฟล็กที่สร้างขึ้น ฉันคิดว่าควรแก้ไขปัญหาของคุณเพราะว่า create ไม่ได้ถูกตั้งค่าในการวนซ้ำครั้งต่อๆ ไป - person Paul McMillan; 29.10.2009
comment
คุณอาจต้องการดูคำถามนี้เพื่อดูข้อมูลเพิ่มเติมว่าเมื่อใดควรใช้สัญญาณและเมื่อใดจึงจะแทนที่การบันทึก: stackoverflow.com/questions/170337/ - person Paul McMillan; 29.10.2009
comment
โธ่! ฉันมีค่าความจริงของการทดสอบสำหรับการตั้งค่าสถานะที่สร้างขึ้นผิดไปเล็กน้อย มันควรจะทำงานตอนนี้... - person Paul McMillan; 29.10.2009
comment
ผู้โพสต์ต้นฉบับไม่ได้ระบุว่าเขาต้องการให้ผู้จัดการถูกเรียกเมื่อมีการสร้างบันทึกใหม่เท่านั้น ดังนั้น การใช้แฟล็ก 'สร้าง' จะไม่สามารถแก้ปัญหาได้ หากต้องเรียกตัวจัดการในการอัพเดตด้วย (ฉันกำลังพยายามค้นหาวิธีแก้ปัญหาที่คล้ายกันด้วยตัวเอง) - person jholster; 22.11.2010
comment
jholster: จากนั้นทริกเกอร์ทุกครั้งที่รัน โดยไม่สนใจอาร์กิวเมนต์ created - person Paul McMillan; 23.11.2010