Джанго-сигналы против триггеров?

Я читал о сигналах 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')

Я хочу, чтобы человек мог присоединиться к команде тогда и только тогда, когда местоположение этого человека находится в пределах набора местоположений этой команды. Я не знаю, как это сделать с обычными реляционными ограничениями, поэтому, насколько мне известно, я вынужден использовать триггеры или сигналы. Моя интуиция подсказывает, что я должен использовать триггеры, но я хочу узнать о лучших практиках.


person Alexander Bird    schedule 21.08.2010    source источник


Ответы (4)


Ни один. Лучшим инструментом для этой работы является проверка модели — вы можете написать собственную проверку правило там, и оно будет применяться в админке и ваших собственных приложениях.

person Daniel Roseman    schedule 21.08.2010
comment
+1: это и простое переопределение save в модели охватывает все базы, с которыми я когда-либо сталкивался. - person S.Lott; 22.08.2010
comment
+1. Сигналы обычно замедляют ваши тесты, если вы загружаете приборы, запускающие сигналы. Трудно обойти это, выполняя disconnect перед тестами и connect после них. - person Manoj Govindan; 22.08.2010
comment
У меня две цели: 1) заставить сайт делать то, что я хочу (подтвердить) 2) поймать меня, когда я совершаю ошибку. С точки зрения № 1 это предложение имеет смысл. С точки зрения № 2, что, если я не использую ModelForm для взаимодействия с БД? в документации говорится: обратите внимание, что валидаторы не будут запускаться автоматически при сохранении модели. Это означает, что теперь я могу случайно потерять целостность данных, поскольку я не вызвал валидатор, вызвав Person.save() перед изменением БД. Но с триггерами невозможно ошибочно обойти триггер. Мои рассуждения имеют смысл? - person Alexander Bird; 25.08.2010
comment
Ну, до определенного момента. Ваша проблема будет заключаться в сообщении пользователю о том, что ограничение сработало - вам нужно будет обернуть каждый вызов ORM в блок try/except, чтобы избежать необработанного исключения db, ведущего к странице 500, и в этот момент вы также можете иметь все равно использовал собственные методы Джанго. - person Daniel Roseman; 25.08.2010
comment
Как упомянул С.Лотт, вы можете добавить правила проверки и переопределить .save() для вызова .full_clean(), чтобы ваши данные проверялись при каждом сохранении. Это может нарушить работу местоположений, которые сохраняют и не корректно обрабатывают ошибки проверки, но это может быть предпочтительнее сохранения неверных данных. Вы правы, что триггер будет труднее обойти. Это также было бы быстрее, поскольку оно будет работать внутри базы данных. Недостатком является то, что его может быть сложнее поддерживать, так как вам придется реализовывать все ваши правила проверки в SQL. - person Cerin; 23.06.2011

Сигналы Django великолепны (проверка тоже великолепна, но иногда вам нужно что-то изменить перед сохранением…). Если вы работаете с базой данных ТОЛЬКО через Django, это действительно хорошая идея - хранить всю логику в одном месте, имхо.

Вот пример, как это работает:

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) 
person Igor Pomaranskiy    schedule 25.01.2012

Вы можете использовать триггеры для обеспечения такого рода ограничений, но я бы не стал полагаться на это. Это можно сделать только как вторичное правоприменение, в то время как первичным является проверка модели, как уже сказал Дэниел.

Что касается триггеров БД и сигналов Django, они больше отличаются друг от друга. Единственная общая вещь, которую они разделяют, заключается в том, что оба вызываются при изменении объекта. Но сущности сильно различаются.

Триггеры отслеживают изменения строк базы данных, поэтому они работают с необработанными табличными данными. Триггерный код запускается СУБД.

В отличие от триггеров сигналы отслеживают изменения объекта домена. В общем случае модель Django состоит из данных из нескольких строк таблицы (учитывайте наследование модели и связанные подмножества объектов). Сигнальный код запускается Django.

person Ihor Kaharlichenko    schedule 21.08.2010

Основные преимущества триггеров перед сигналами:

  • независимо от приложения: упрощает переход на новые фреймворки/языки (поскольку триггеры и, в некоторых случаях, хранимые процедуры выгружаются вместе с вашей БД)

  • безопасность: в зависимости от ситуации вы можете ограничить права на ОБНОВЛЕНИЕ для некоторых таблиц и по-прежнему иметь возможность запускать свое приложение (подумайте о критической истории или таблицах транзакций, кто знает, какие эксплойты могут быть обнаружены в следующем 10 лет)

  • уменьшите количество запросов, которые ваше приложение должно адресовать СУБД (особенно полезно в контексте распределенной архитектуры).

Вот основные преимущества. Основной минус заключается в том, что вам придется иметь дело с синтаксисом SQL старой школы.

person zar3bski    schedule 14.12.2018