django - 如何在 Django 中执行昂贵操作的循环期间跳过已删除的模型?
问题描述
我有一个名为设备的模型。每个设备都有一个data_downloaded()
anddata_uploaded()
方法,它在数据库中查找与该设备相关的所有记录,并总结他们使用的数据。每个设备都可能有数千条记录,需要汇总以计算其使用情况。我的模型如下所示:
class Device(models.Model):
...
mac_address = models.CharField(...)
data_downloaded_cached = models.BigIntegerField(...)
data_uploaded_cached = models.BigIntegerField(...)
def data_downloaded(self):
return DataRecord.objects.filter(mac_address=self.mac_address, direction="download").aggregate(data=Sum('data')).get("data", 0.00) or 0.00
def data_uploaded(self):
return DataRecord.objects.filter(mac_address=self.mac_address, direction="upload").aggregate(data=Sum('data')).get("data", 0.00) or 0.00
class DataRecord(models.Model):
timestamp = models.DateTimeField(...)
mac_address = models.CharField(...)
direction = models.CharField(...)
data = models.BigIntegerField(...)
由于device.data_downloaded()
和device.data_uploaded()
是昂贵的操作,可能需要一分钟的时间来计算(需要聚合大量数据库行),所以我不能在加载模板时直接调用这些方法,所以我缓存了这些值。后台进程运行以下代码以每隔几分钟更新这些缓存值:
for device in Device.objects.all():
device.data_downloaded_cached = device.data_downloaded()
device.data_uploaded_cached = device.data_uploaded()
device.save()
当模板显示设备列表以及每个设备的下载和上传值时,它们可以只使用缓存的值,而不是尝试即时运行这些昂贵的操作,这将导致模板永远加载用户的浏览器。
我遇到的问题是:
- 如果在上面的代码运行时设备被删除,该设备仍将由 for 循环处理
- 当循环到达已删除的设备,计算值并调用
device.save()
时,保存操作将取消删除已删除的设备(在数据库中重新创建)
我显然不关心更新最近删除的设备的缓存值。我也不想在这些昂贵的操作发生时一次锁定数据库几分钟。如何确保跳过已删除的设备?
注意:可以在昂贵的操作开始之前或之后删除设备。我关心的主要事情是确保device.save()
不会重新创建设备。如果我能确保在这些操作开始之前已删除的设备上不会执行昂贵的操作,那就太好了。如果没有,我只需要确保已删除的设备不会被重新创建device.save()
编辑:根据 Willem Van Onsem 的建议,我可以这样做:
totals = DataRecord.objects.values('mac_address').order_by('mac_address').annotate(downloaded=Sum('data', filter=Q(direction="download"))).annotate(uploaded=Sum('data', filter=Q(direction="upload")))
updates = []
for device in totals:
dev = Device.objects.filter(mac_address=device['mac_address']).first()
if dev:
dev.data_downloaded_cached = device["downloaded"]
dev.data_uploaded_cached = device["uploaded"]
updates.append(dev)
Device.objects.bulk_update(updates, ['data_downloaded_cached', 'data_uploaded_cached'])
听起来对吗?
解决方案
推荐阅读
- geb - 不太确定如何在不使用 nth-child 的情况下使用 Geb 找到定位器
- java - 列出和读取 JAR 文件中 java 包中的所有文件不起作用
- azure - 天蓝色故障转移后,无法 RDP 到 VM,也无法更改 azure 站点恢复中的恢复点
- azure - 如何从 Azure Databricks 将 JSON 写入 Azure 队列
- c# - JwtBearerEvents 中的依赖注入
- magento2 - 通过 Installatron 脚本安装后 CSS 未在前端和后端加载
- excel - 是否可以使用 vba 在 excel 中更改构建查找替换对话框?
- javascript - 初学者的 HTTP GET 请求 - Octoprint
- ffmpeg - 为什么 ffmpeg 在接收 MPEG TS 格式的流时显示损坏的视频?
- php - REST服务中Solr PHP客户端配置管理的有效方法