2009-10-28 96 views
10

我試圖在保存後立即更新記錄。這個例子看似毫無意義,但想象一下,我們需要使用一個API的數據被保存到獲得一些額外的信息和更新的記錄後:django中的post_save立即更新實例

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) 

所以「額外」字段應該設置爲「你好」每次保存後。正確?但它不起作用。

任何想法?

+0

也許你可以描述它是如何工作的?乍一看,它似乎會造成一個無限循環,因爲post_save調用保存,它應該調用post_save等。也許Django阻止遞歸? – 2009-10-28 23:21:36

+0

我在那裏看到一個無限循環。在t.save()發送post_save信號之後,猜猜哪個函數被調用... – stefanw 2009-10-28 23:22:04

+0

哦,我印象中Django不會讓第二個保存觸發post_save呢?我猜不會。在這種情況下,你是對的。這將是一個無限循環。但我沒有看到循環或任何東西。 – givp 2009-10-28 23:28:53

回答

18

當您發現自己使用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) 
+1

如果他正在對管理模型執行此操作,則post_save是比繼承現有管理模型和覆蓋保存更好的解決方案。 – 2009-10-29 00:46:28

+0

@保羅麥克米蘭爲什麼? – 2011-03-25 16:32:39

+0

在Django 1.3和更高版本的'save'方法參數列表中需要'using = False' – eviltnan 2012-07-20 13:11:47

6

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()方法。

+0

我其實也試過,也無濟於事。但是如果上面的人是正確的,我不能這樣做,因爲它會卡在post_save循環中。 – givp 2009-10-28 23:30:03

+0

嘗試使用創建的標誌。我認爲這應該解決你的問題,因爲創建的後續循環通過未設置。 – 2009-10-28 23:31:34

+1

你可能想看看這個問題的更多信息,何時使用信號以及何時重寫保存:http://stackoverflow.com/questions/170337/django-signals-vs-overriding-save-method – 2009-10-28 23:34:13