2012-08-05 117 views
8

假設我有一個名爲Hero的類,名爲「name」。每次創建一個新的英雄對象時,我都要追加" is a hero"。我可以使用__init__嗎?或者是否有一個我可以重寫的特定於Django的方法?django模型創建使用__init__?

class Hero(modes.Model) 
    name = models.CharField(max_length=100) 
    def __init__(self, *args, **kwargs): 
     name += " is a hero" 
     super(Hero, self).__init__(*args, **kwargs) 
+1

這幾乎從來沒有你想要的。描述你真正的問題。 – 2012-08-05 23:27:38

+0

@ IgnacioVazquez-Abrams我必須更新另一個基於我的Hero類的聚合輸入的模型。 – Joey 2012-08-05 23:37:09

+1

@Joey改爲使用[signals](https://docs.djangoproject.com/en/1.4/topics/signals/)。 – Dougal 2012-08-05 23:50:30

回答

15

如果「每次創建一個新的英雄對象時,」你的意思是「每一個英雄記錄在數據庫中創建時間」,那麼不,你不希望這樣做的__init__方法,因爲任何時候在Python中創建一個Hero對象時都會調用這個對象,包括何時從數據庫中獲取現有記錄。

要做你想做的事,你可以使用Django的post_save signal,在信號回調中檢查created關鍵字參數是否爲True,如果是,執行你的「on creation」邏輯。

或者,更直接和自然在某些情況下,您可以覆蓋英雄的save()方法如下:

def save(self, *args, **kwargs): 
    if not self.pk: # object is being created, thus no primary key field yet 
     self.name += " is a hero" 
    super(Hero, self).save(*args, **kwargs) 

注意Djagno的bulk_create方法會跳過觸發或者後保存信號或致電save

+4

作爲[文檔解釋](https://docs.djangoproject.com/en/1.4/topics/db/models/#overriding-model-methods),你應該總是包含'* args'和'** kwargs'在調用父類的'save'方法時,* ie *'super(Hero,self).save(* args,** kwargs)'。原因是爲了防止將更改(在Django或您的代碼中)更改爲'save()'方法的簽名。 – supervacuo 2012-08-06 04:24:08

+1

@supervacuo - 很好,我已經編輯過,謝謝。 – Ghopper21 2012-08-06 04:32:07

+1

作爲未來讀者的警告,重寫'save'並非普遍安全。 [批量保存不會調用重載的保存方法或調用'post_save'和'pre_save'信號](https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-model-methods)。我不確定Django是否提供了對批量更新或創建進行自定義的方法,儘管它看起來不像它,所以您應該小心如何做到這一點,並確保在您防守時不會發生批量保存關於自定義更新行爲。 – Taywee 2017-03-10 22:11:08