2010-08-21 43 views
10

我讀了關於django信號(http://docs.djangoproject.com/en/dev/topics/signals/),但據我所知,信號從未轉換爲文字SQL觸發器(http://en.wikipedia.org/wiki/Database_trigger)。django-signals vs觸發器?

如果我是正確的信號和觸發器是不同的,那哪一個更好,以什麼方式?最佳做法是什麼?

....................

這裏有一個具體的例子,如果你想要一個:

class Location(models.Model): 
    name = models.CharField(max_length=30) 

class Person(models.Model): 
    location = models.ForeignKey('Location') 

class Team(models.Model): 
    locations = models.ManyToManyField('Location') 

我想一個人要當且僅當該人的位置在該球隊的一組位置內時才能加入球隊。我不知道如何做到這一點與正常的關係約束,所以據我所知,我不得不使用觸發器或信號。我的直覺說我應該使用觸發器,但我想知道最佳實踐。

回答

14

也沒有。這項工作的最佳工具是model validation - 您可以在那裏編寫自定義驗證規則,它將在管理員和您自己的應用中執行。

+0

+1:這和簡單的覆蓋,以'模型save'涵蓋我一生中遇到的所有基地。 – 2010-08-21 22:58:41

+0

+1。如果您正在加載觸發信號的燈具,信號通常會減慢測試速度。在測試和之後的連接之前,通過「斷開連接」來解決是一件很痛苦的事情。 – 2010-08-22 06:45:03

+1

我有兩個目標: 1)使網站做我想要的(驗證) 2)當我* *犯錯時抓住我。 就#1而言,這個建議很有意義。 就#2而言,如果我不使用ModelForm與數據庫進行交互,該怎麼辦?該文檔中提到「請注意,保存模型時驗證器不會自動運行」。這意味着我現在可能會意外丟失數據完整性,因爲在修改數據塊之前我沒有通過調用Person.save()來調用驗證器。 但是對於觸發器,觸發器不可能被錯誤地繞過。 我的推理是否有意義? – 2010-08-24 21:14:04

1

你可以使用觸發器來強制執行這種約束,但我不會依賴這個。這隻能作爲輔助執行來完成,而主要方法是進行模型驗證,就像Daniel已經說過的那樣。

至於DB 觸發器與Django 信號他們有更多不同之處。他們分享的唯一共同點是兩者都是在實體變更時被調用的。但實體差異很大。

觸發器監視數據庫行更改,因此它們對原始表格數據進行操作。觸發器代碼由DBMS運行。

與觸發器信號對比監控域對象更改。在一般情況下,Django的模型由來自多個錶行的數據組成(考慮模型繼承和相關對象子集)。信號代碼由Django運行。

6

Django信號很棒(驗證也很棒,但有時需要更改,然後才能保存...)。如果你只是通過Django使用數據庫,那麼把所有的邏輯放在同一個地方,imho是個好主意。

下面是一個例子,它是如何工作:

class Example(models.Model): 
    ''' Example of Model (I hate foo-bars!) ''' 
    age = models.IntegerField() 
    can_buy_beer = models.BooleanField(default=False) 


def set_can_buy_beer(sender, instance, **kwargs): 
    ''' Trigger body ''' 
    if instance.age >= 21: 
     instance.can_buy_beer = True 
    else: 
     instance.can_buy_beer = False 

# ↓ Magic — now, field Example.can_buy_beer will be autocalculated on each save! 
pre_save.connect(set_can_buy_beer, sender=Example)