Sql django信号vs触发器?
我读过django signals(),但据我所知,信号从未转换成文字SQL触发器() 如果我正确地认为信号和触发器是不同的,那么哪一个更好,在哪些方面更好?最佳做法是什么 下面是一个具体的例子,如果您需要: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
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中实现所有验证规则。