[英]How to get a models with highest value grouped by related model in django?
我想在 Django 中执行这个查询:
For each sensor, select it's latest message
在 SQL 中,它类似于
SELECT * FROM (SELECT * FROM messages order by date_entered DESC) as order GROUP BY sensor_id
模型是这样定义的
class BaseModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
date_entered = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
deleted = models.IntegerField(default=0)
class Meta:
abstract = True
ordering = ['date_modified']
class Device(BaseModel):
user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
name = models.CharField(max_length=255, blank=False)
identifier = models.CharField(max_length=31, blank=False)
imei = models.CharField(max_length=31, blank=False)
status = models.CharField(max_length=31, blank=False)
settings = models.TextField()
class DeviceMessage(BaseModel):
device = models.ForeignKey(Device, on_delete=models.SET_NULL, blank=True, null=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
latitude = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True)
longitude = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True)
altitude = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
signal_strength = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
battery = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
satellites = models.IntegerField(blank=True, null=True)
size = models.IntegerField(blank=True, null=True)
raw = models.TextField(blank=True, null=True)
有可能在 Django 中实现这一点吗?
基本上就是这个问题Using ORDER BY and GROUP BY together
从 Django 1.11 开始,您可以使用Subquery 功能来注释数据:
from django.db.models import OuterRef, Subquery
latest = DeviceMessage.objects.filter(device_id=OuterRef('pk')).order_by('-date_entered')
devices = Device.objects.annotate(latest_message_id=Subquery(latest.values('pk')[:1]))
message_ids = [d.latest_message_id for d in devices]
for message in DeviceMessage.objects.filter(pk__in=message_ids).select_related('device'):
print(device.name, message)
......
“对于每个传感器,选择它的最新消息”
我假设“传感器”是指Device
模型。 在这种情况下(因为您现在已经阐明BaseModel
是一个抽象基类),它就像这样简单( sensor
是您要查询的特定Device
实例):
sensor.devicemessage_set.order_by("-date_entered")[0]
如果您想一次为多个传感器查找此信息,最好使用annotation ,例如:
from django.db.models import Max
...
Device.objects.all().annotate(latest_msg=Max("devicemssage_set__date_entered"))
这为每个Device
对象提供了一个名为latest_msg
的(临时)属性,其中包含您想要的信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.