Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql django信号vs触发器?_Sql_Django_Triggers_Django Signals - Fatal编程技术网

Sql django信号vs触发器?

Sql django信号vs触发器?,sql,django,triggers,django-signals,Sql,Django,Triggers,Django Signals,我读过django signals(),但据我所知,信号从未转换成文字SQL触发器() 如果我正确地认为信号和触发器是不同的,那么哪一个更好,在哪些方面更好?最佳做法是什么 下面是一个具体的例子,如果您需要: class Location(models.Model): name = models.CharField(max_length=30) class Person(models.Model): location = models.ForeignKey('Location

我读过django signals(),但据我所知,信号从未转换成文字SQL触发器()

如果我正确地认为信号和触发器是不同的,那么哪一个更好,在哪些方面更好?最佳做法是什么

下面是一个具体的例子,如果您需要:

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

我希望一个人能够加入一个团队,当且仅当该人的位置在该团队的位置集中时。我不知道如何使用正常的关系约束来实现这一点,所以据我所知,我被迫使用触发器或信号。我的直觉告诉我应该使用触发器,但我想知道最佳实践。这项工作的最佳工具是——你可以在那里编写自定义验证规则,它将在管理员和你自己的应用程序中强制执行。

你可以使用触发器强制执行此类约束,但我不会依赖于此。正如Daniel已经说过的,这只能作为次要的强制执行,而主要的是模型验证

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

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


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

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) 

触发器相对于信号的主要优势:

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

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

  • 减少应用程序必须向DBMS发送的请求数量(在分布式体系结构环境中尤其有用)


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

+1:这和模型中对
保存的简单重写涵盖了我遇到的所有基础。+1。如果加载触发信号的装置,信号通常会减慢测试速度。在测试前断开连接,然后再连接,这是一种痛苦。我有两个目标:1)让网站做我想做的(验证)2)在我犯错误时抓住我。就#1而言,这一建议是有道理的。就#2而言,如果我不使用ModelForm与DB交互会怎么样?文档中说“请注意,保存模型时,验证器不会自动运行”。这意味着我现在可能会意外地丢失数据完整性,因为在修改数据库之前,我没有通过调用
Person.save()
来调用验证器。但是有了触发器,就不可能错误地规避触发器。我的推理有意义吗?嗯,在一定程度上。您的问题在于向用户报告约束已运行-您需要将每个ORM调用包装在一个try/except块中,以避免未经处理的db异常导致500页,此时您可能已经使用了Django自己的方法。正如s.Lott提到的,您可以添加验证规则并覆盖.save()调用.full_clean()以确保每次保存时都检查数据。这可能会破坏保存的位置,并且无法正常处理验证错误,但这可能比保存无效数据更可取。你说得对,扳机更难绕过。它也会更快,因为它将在数据库中运行。缺点是它可能更难维护,因为您必须在SQL中实现所有验证规则。