16

我阅读了 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')

当且仅当该人的位置在该团队的一组位置内时,我希望该人能够加入团队。我不知道如何使用正常的关系约束来做到这一点,所以据我所知,我被迫使用触发器或信号。我的直觉说我应该使用触发器,但我想知道最佳实践。

4

4 回答 4

22

两者都不。这项工作的最佳工具是模型验证- 您可以在那里编写自定义验证规则,它将在管理员和您自己的应用程序中强制执行。

于 2010-08-21T22:03:30.247 回答
12

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) 
于 2012-01-25T13:27:24.910 回答
4

您可以使用触发器来强制执行这种约束,但我不会依赖它。这只能作为辅助执行,而主要是模型验证,正如丹尼尔已经说过的那样。

至于 DB触发器与 Django信号,它们更常见。它们共享的唯一共同点是两者都在实体更改时被调用。但实体差异很大。

触发器监视数据库行更改,因此它们对原始表格数据进行操作。触发代码由 DBMS 运行。

与触发信号相反,监控域对象的变化。在一般情况下,Django 的模型由来自多个表行的数据组成(考虑模型继承和相关的对象子集)。信号代码由 Django 运行。

于 2010-08-21T22:25:16.687 回答
4

触发器优于信号的主要优点:

  • 独立于应用程序:使迁移到新框架/语言更容易(因为触发器,在某些情况下,存储过程与您的数据库一起转储)

  • 安全性:根据情况,您可以限制某些表的 UPDATE 权限,并且仍然能够运行您的应用程序(想想关键历史记录或事务表,谁知道未来 10 年可能会发现哪些漏洞)

  • 减少您的应用程序必须向 DBMS 处理的请求数量(在分布式架构的上下文中尤其有用)。

以下是主要优点。主要缺点是您必须处理旧的 SQL 语法。

于 2018-12-14T20:35:26.643 回答