You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django多模型关联查询:获取当前用户各设备最新Report

解决方法:获取用户每台设备的最新Report

方法一:使用Subquery(高效兼容多数据库)

这是性能最优的方案,适合数据量较大的场景,兼容MySQL、PostgreSQL等主流数据库。

首先导入所需模块:

from django.db.models import Subquery, OuterRef

然后构建查询:

# 子查询:获取每个设备最新Report的ID
latest_report_ids = Report.objects.filter(
    device_id=OuterRef('pk')
).order_by('-date').values('pk')[:1]

# 筛选当前用户的设备,并关联最新Report的ID
user_devices = Device.objects.filter(owner=request.user).annotate(
    latest_report_id=Subquery(latest_report_ids)
)

# 最终获取所有最新的Report记录
latest_reports = Report.objects.filter(
    pk__in=user_devices.values('latest_report_id')
).select_related('device_id')

方法二:使用distinct + order_by(代码简洁,依赖数据库特性)

此方法仅支持PostgreSQL(MySQL不支持带字段的distinct),代码最简洁:

latest_reports = Report.objects.filter(
    device_id__owner=request.user
).order_by('device_id', '-date').distinct('device_id')

原理:先按设备分组,再按日期倒序排序,distinct('device_id')会保留每个设备的第一条(最新)记录。

方法三:循环查询(直观但低效)

如果设备数量很少,可以用这种直观但有N+1查询问题的方式,不推荐大量设备场景:

user_devices = Device.objects.filter(owner=request.user)
latest_reports = []
for device in user_devices:
    # 获取当前设备的最新Report
    latest_report = device.report_set.order_by('-date').first()
    if latest_report:
        latest_reports.append(latest_report)

额外优化建议

模型中Report的外键字段名device_id容易和Device的device_id字段混淆,建议修改命名规范:

class Report(models.Model):
    # 重命名外键字段,添加related_name方便反向查询
    device = models.ForeignKey('Device', on_delete=models.CASCADE, related_name='reports')
    coordinates = models.JSONField(null=True)
    fill = models.IntegerField()
    date = models.DateTimeField()

    def __str__(self):
        return str(self.device.device_id)

之后可以用device.reports替代device.report_set,代码可读性更高。

内容的提问来源于stack exchange,提问作者Jaime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:10:05