为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Django 模型中违反约束时增加唯一时间戳?

如何在 Django 模型中违反约束时增加唯一时间戳?

潇湘沐 2023-09-26 17:13:05
作为使用 TimescaleDB 的一部分,它需要时间戳作为主键(SensorReading 中的时间),我需要处理不同传感器值使用相同时间戳的情况。一个优雅的解决方案可能是涂抹碰撞时间戳(在碰撞时添加一微秒)。对于以下模型,如何以稳健且高性能的方式解决这个问题?class Sensor(models.Model):    name = models.CharField(max_length=50)class SensorReading(models.Model):    time = models.DateTimeField(primary_key=True, default=datetime.now)    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)    value = models.FloatField()PS 这是一个解决方法,因为 Django 不支持复合主键。否则,可以将传感器和时间戳设置为复合主键。
查看完整描述

3 回答

?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

为了使用 timescale db,我创建了一个虚拟主键字段,它会欺骗 Django 并将复合键值表示为单个 json 元组。

查看完整回答
反对 回复 2023-09-26
?
侃侃尔雅

TA贡献1801条经验 获得超15个赞

我发现的一种解决方案是在模型保存调用周围使用 try/ except 块。尝试添加传感器读数,大多数情况下都会成功,但如果发生碰撞,请处理该错误。确保抛出的异常正是由于该冲突而引起的,然后将时间戳增加一微秒(最小分辨率)。然后重复尝试保存传感器读数。由于首先发生的碰撞概率较低,因此这几乎总是会成功。下面是经过测试的代码,用于递归地处理递增时间戳直到成功。


class SensorReading(models.Model):

    time = models.DateTimeField(primary_key=True, default=datetime.now)

    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)

    value = models.FloatField()


    def save(self, *args, **kwargs):

        self.save_increment_time_on_duplicate(*args, **kwargs)

    

    def save_increment_time_on_duplicate(self, *args, **kwargs):

        try:

            super().save(*args, **kwargs)

        except IntegrityError as exception:

            if all (k in exception.args[0] for k in ("Key","time", "already exists")):

                self.time = str(parse_datetime(self.time) + timedelta(microseconds=1))

                self.save_increment_time_on_duplicate(*args, **kwargs)

更稳健的实现还可能在中止之前添加最大尝试次数。


查看完整回答
反对 回复 2023-09-26
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

一般来说,我建议至少在某种程度上从 Django 中获取该传感器表的表管理,使用 psycopg2 或其他驱动程序进行插入,并在 上创建适当的主键,然后公开该表(或Sensor, time在它)作为一个 Django 模型,它可以从中读取,如果需要的话,也许可以使用连接。这些应该写入一次,因此您不必处理更新,这通常就是它需要非复合主键的原因。在某些时候 Django 应该真正开始支持复合主键,但遗憾的是他们没有。

其他方法可能有效,但它们可能根本无法很好地扩展。因此,如果您关心摄取率,我可能会尝试不同的方法。


查看完整回答
反对 回复 2023-09-26
  • 3 回答
  • 0 关注
  • 103 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信