我不确定我是否为需要的内容加上了正确的标题,但这就是问题。 我有两个模型。
class Device(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
device_name = models.CharField(max_length=200, null=True, blank=True )
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.device_name)
class StatusActivity(models.Model):
OFFLINE = 1
ONLINE = 2
STATUS = (
(OFFLINE, ('Offline')),
(ONLINE, ('Online')),
)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
device_id = models.ForeignKey(Device, related_name='status_activity', on_delete=models.CASCADE)
status = models.PositiveSmallIntegerField(choices=STATUS)
modified_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.device_id)
我可以分别获取StatusActivity和设备的列表。但是我需要的是每台设备的最新状态。
设备:
Id Created_At Device_name
5b9bbd0f02f8428ca69a582a491f0751 2019-11-30 15:38:37.076440 Temperature Device
17c1ac3ed05844cd879c218effaba15e 2019-11-30 15:39:14.716443 Humidity Device
a0ca21a555b246b99be965db4493276f 2019-11-30 15:39:27.822114 Motion Device
StatusActivities:
Id Status Modified_at Device_id_id
350fed049ba04541a7b6d81932d5824b 2 2019-11-30 15:39:39.849491 5b9bbd0f02f8428ca69a582a491f0751
e4f317b56bbb46eb9309ba77da692af0 1 2019-11-30 15:39:47.912013 5b9bbd0f02f8428ca69a582a491f0751
e0a021dd53734d3b9a15e53ad93bbb28 2 2019-11-30 15:41:04.891823 5b9bbd0f02f8428ca69a582a491f0751
1c12c64708234df6992883b377d3102f 2 2019-11-30 17:12:58.336177 17c1ac3ed05844cd879c218effaba15e
8d280d522baa449588b9a9ab67ed7bae 1 2019-11-30 17:13:05.987487 a0ca21a555b246b99be965db4493276f
示例结果应为:
ID device_name Status Modified_at
5b9bbd0f02f8428ca69a582a491f0751 Temperature Device 2 2019-11-30 15:39:39.849491
17c1ac3ed05844cd879c218effaba15e Humidity Device 2 2019-11-30 17:12:58.336177
a0ca21a555b246b99be965db4493276f Motion Device 1 2019-11-30 17:13:05.987487
答案 0 :(得分:0)
如果您使用的是Postgres,则可以在DISTINCT ON
上使用distinct
(device_id
):
from django.db.models import F
StatusActivity.objects.order_by('device_id', '-modified_at').distinct('device_id').annotate(
ID=F('device_id__id'),
device_name=F('device_id__device_name'),
).values('ID', 'device_name', 'status', 'modified_at')
如果您没有Postgres,则可以使用子查询来注释StatusActivity
中的数据:
from django.db.models import Subquery, OuterRef
Device.objects.annotate(
status=Subquery(
StatusActivity.objects.filter(
device_id=OuterRef('pk')
).order_by('-modified_at').values('status')[:1]
),
modified_at=Subquery(
StatusActivity.objects.filter(
device_id=OuterRef('pk')
).order_by('-modified_at').values('modified_at')[:1]
),
).values('id', 'device_name', 'status', 'modified_at')
注意事项:
Subquery
仅需要一行和一列,因此可以在注释中使用该值。这意味着,如果我们想从一个子查询中获得多个列,则需要使用两个注释,以便像上面那样有两个联接,这样会影响性能。status
,但如果您希望同时使用这两个字段,则建议您采用第一种方法(假设您使用的是受支持的数据库(Postgres))。还请注意,Django会自动将_id
附加到FK字段,因此最好将它们命名为不带任何_id
后缀。在您的情况下,请使用device
而不是device_id
。