views:

70

answers:

2

I read about django signals (http://docs.djangoproject.com/en/dev/topics/signals/), but as far as I understand, signals are never converted into literal SQL triggers (http://en.wikipedia.org/wiki/Database_trigger).

If I'm correct that signals and triggers are different, then which one is better and in what ways? What's the best practice?

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

Here's a concrete example if you want one:

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

I want a person to be able to join a team if and only if that person's location is within that team's set of locations. I do not know how to do that with normal relational constraints, so as far as I know I'm forced to use triggers or signals. My gut says that I should use triggers but I want to know best practice.

+4  A: 

Neither. The best tool for this job is model validation - you can write your custom validation rule there and it will be enforced in the admin and your own apps.

Daniel Roseman
+1: That and a simple override to `save` in the model covers all the bases I've ever encountered.
S.Lott
+1. Signals usually slow your tests down if you are loading fixtures that trigger signals. It is a pain to work around by `disconnect` ing before tests and `connect` ing afterwards.
Manoj Govindan
I have two goals:1) make the site do what I want (validate)2) catch me when *I* make a mistake.In terms of #1, this suggestion makes sense.In terms of #2, what if I don't use a ModelForm to interact with the DB? the documentation says "Note that validators will not be run automatically when you save a model". That means I now can accidentally lose data integrity since I didn't invoke a validator by calling `Person.save()` before modifying the DB.But with triggers, it's impossible for the trigger to be mistakingly circumvented.Does my reasoning make sense?
Thr4wn
Well, up to a certain point. Your problem will be in reporting to the user that the constraint has operated - you'll need to wrap every ORM call in a try/except block to avoid an unhandled db exception leading to a 500 page, at which point you may as well have used Django's own methods anyway.
Daniel Roseman
+1  A: 

You can use triggers to enforce this kind of constraints, but I wouldn't rely on that. This can only be done as a secondary enforcement, while the primary one is to be model validation, just as Daniel already said.

As for DB triggers vs Django signals they are more different the common. The only common thing they share is that both are invoked upon entity change. But the entities differ very much.

Triggers monitor database row changes, thus they operate on raw tabular data. Trigger code is run by DBMS.

In contrast to triggers signals monitor domain object changes. In a generic case Django's model consists of data from several table rows (consider model inheritance and related object subsets). Signal code is run by Django.

Ihor Kaharlichenko