Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

Django signals are awesome (validation is awesome too, but sometimes you need to change something before save…). If you are working with database ONLY thru Django, it's really good idea to keep all logic in same place, imho.

Here is an example, how it works:

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) 

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.

Main advantages of Triggers over Signals:

  • independent of the application: makes the migration to a new frameworks/languages easier (since triggers and, in some cases, stored procedure are dump with your DB)

  • safety: depending on the situation, you could restrict the UPDATE rights on some tables and still be able to run your app (think of critical history or transaction tables, who knows which exploits might be discovered in the next 10 years)

  • reduce the number of requests your app have to address to the DBMS (especially useful in the context of a distributed architecture).

Here are the main advantages. The main cons is that you have to deal with the old school SQL syntax.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top