Ответ 1
Ни. Лучшим инструментом для этой работы является проверка модели - вы можете написать свое собственное правило проверки, и оно будет применено в администраторе и ваших собственных приложениях.
Я читал о сигналах django (http://docs.djangoproject.com/en/dev/topics/signals/), но, насколько я понимаю, сигналы никогда не преобразуются в литературные триггеры SQL (http://en.wikipedia.org/wiki/Database_trigger).
Если я прав, что сигналы и триггеры различны, то какой из них лучше и какими способами? Какая лучшая практика?
....................
Вот конкретный пример, если вы хотите его:
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')
Я хочу, чтобы человек мог присоединиться к команде в том и только в том случае, если это место находится в пределах этого набора команд. Я не знаю, как это сделать с нормальными реляционными ограничениями, насколько я знаю, я вынужден использовать триггеры или сигналы. Моя кишка говорит, что я должен использовать триггеры, но я хочу знать лучшие практики.
Ни. Лучшим инструментом для этой работы является проверка модели - вы можете написать свое собственное правило проверки, и оно будет применено в администраторе и ваших собственных приложениях.
Сигналы 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)
Вы можете использовать триггеры для принудительного применения таких ограничений, но я бы не стал на это полагаться. Это можно сделать только в качестве вторичного принудительного исполнения, в то время как первичный - это проверка модели, как уже сказал Даниэль.
Что касается триггеров DB против сигналов Django, они более разные. Единственная распространенная вещь, которую они разделяют, заключается в том, что оба вызываются при изменении сущности. Но сущности сильно отличаются.
Триггеры отслеживают изменения строки базы данных, поэтому они работают с необработанными табличными данными. Триггерный код запускается СУБД.
В отличие от триггеров, сигналы отслеживают изменения объекта домена. В общем случае модель Django состоит из данных из нескольких строк таблицы (рассмотрим наследование модели и связанные с ней подмножества объектов). Сигнальный код запускается Django.
Основные преимущества триггеров над сигналами:
не зависит от приложения: упрощает переход на новые фреймворки/языки (поскольку триггеры и, в некоторых случаях, хранимые процедуры сбрасываются с вашей БД)
безопасность: в зависимости от ситуации вы можете ограничить права UPDATE для некоторых таблиц и по-прежнему иметь возможность запускать ваше приложение (подумайте о критической истории или таблицах транзакций, которые знают, какие эксплойты могут быть обнаружены в ближайшие 10 лет)
уменьшить количество запросов, которые ваше приложение должно адресовать к СУБД (особенно полезно в контексте распределенной архитектуры).
Вот основные преимущества. Основным недостатком является то, что вам приходится иметь дело с синтаксисом SQL старой школы.