2010-08-21 11 views
10

Ich lese über Django-Signale (http://docs.djangoproject.com/en/dev/topics/signals/), aber soweit ich verstehe, werden Signale nie in literale SQL-Trigger (http://en.wikipedia.org/wiki/Database_trigger) konvertiert.Django-Signale vs Trigger?

Wenn ich richtig bin, dass Signale und Trigger unterschiedlich sind, welche ist dann besser und auf welche Weise? Was ist die beste Praxis?

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

Hier ist ein konkretes Beispiel, wenn Sie eine wollen:

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') 

Ich möchte eine Person sein, Sie können nur dann einem Team beitreten, wenn sich der Standort dieser Person innerhalb der Standortgruppe dieses Teams befindet. Ich weiß nicht, wie man das mit normalen relationalen Einschränkungen macht, also bin ich, soweit ich weiß, gezwungen, Trigger oder Signale zu verwenden. Mein Bauchgefühl sagt, dass ich Trigger verwenden sollte, aber ich möchte Best Practice wissen.

Antwort

14

Weder. Das beste Tool für diesen Job ist model validation - Sie können dort Ihre benutzerdefinierte Validierungsregel schreiben und sie wird in den Admin- und Ihren eigenen Apps erzwungen.

+0

+1: Das und eine einfache Überschreibung 'save' im Modell deckt alle Basen ich je erlebt habe. –

+0

+1. Signale verlangsamen normalerweise Ihre Tests, wenn Sie Fixtures laden, die Signale auslösen. Es ist mühsam, vor dem Test zu "trennen" und danach zu "verbinden". –

+1

Ich habe zwei Ziele: 1) machen Sie die Website tun, was ich will (gültig) 2) fange mich, wenn * ich * einen Fehler mache. In Bezug auf # 1 macht dieser Vorschlag Sinn. In Bezug auf # 2, was ist, wenn ich nicht ein ModelForm verwenden, um mit der DB zu interagieren? In der Dokumentation heißt es: "Beachten Sie, dass Validatoren beim Speichern eines Modells nicht automatisch ausgeführt werden." Das bedeutet, dass ich jetzt die Datenintegrität verlieren kann, da ich keinen Validator aufgerufen habe, indem ich "Person.save()" aufgerufen habe, bevor ich die Datenbank ändere. Aber mit Auslösern ist es unmöglich, dass der Auslöser fälschlicherweise umgangen wird. Macht meine Argumentation Sinn? –

1

Sie können Auslöser verwenden, um diese Art von Einschränkungen zu erzwingen, aber ich würde mich nicht darauf verlassen. Dies kann nur als sekundäre Erzwingung geschehen, während die erste eine Modellvalidierung ist, wie Daniel bereits gesagt hat.

Wie für DB löst vs Django Signale sie die gemeinsame mehr unterschiedlich sind. Die einzige Gemeinsamkeit, die sie teilen, ist, dass beide bei einer Änderung der Entität aufgerufen werden. Aber die Entitäten unterscheiden sich sehr.

Trigger Monitor Datenbank Zeilenänderungen, so dass sie auf rohen Tabellendaten arbeiten. Der Triggercode wird von DBMS ausgeführt.

Im Gegensatz zu Triggern Signale Monitor Domänenobjekt ändert. In einem generischen Fall besteht das Django-Modell aus Daten aus mehreren Tabellenzeilen (betrachten Sie Modellvererbung und verwandte Objektuntergruppen). Signalcode wird von Django ausgeführt.

6

Django Signale sind genial (Validierung ist auch toll, aber manchmal brauchen Sie zu ändern etwas vor speichern ...). Wenn du nur mit Django mit der Datenbank arbeitest, ist es wirklich eine gute Idee, alle Logik an derselben Stelle zu behalten, imho. Hier

ist ein Beispiel, wie es funktioniert:

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)