Django ORM - Get Max group by



我有三个模型。

数据中心

class Datacenter(models.Model):
"""
Datacenter
"""
uuid = models.UUIDField(verbose_name=_('UUID'), unique=True, default=uuid.uuid1, editable=False)
name = models.CharField(_('name'), max_length=80, db_index=True)
price_per_gigabyte = models.DecimalField(_('price per gigabyte'), max_digits=36, decimal_places=18, default=0, db_index=True)
class Meta:
verbose_name = _('datacenter')
verbose_name_plural = _('datacenters')
ordering = ['name']
def __str__(self):
return f'{self.name} / ${self.price_per_gigabyte:.2f} per GB'

服务器

class Server(models.Model):
"""
Server
"""
uuid = models.UUIDField(verbose_name=_('UUID'), unique=True, default=uuid.uuid1, editable=False)
hostname = models.CharField(_('hostname'), max_length=253, db_index=True)
datacenter = models.ForeignKey(Datacenter, models.PROTECT, related_name="servers", related_query_name="server", verbose_name=_('datacenter'))
useful_storage_capacity = models.PositiveSmallIntegerField(_('useful storage capacity'), default=0, db_index=True)
class Meta:
verbose_name = _('server')
verbose_name_plural = _('servers')
ordering = ['hostname']
def __str__(self):
return self.hostname

存储

class Storage(models.Model):
"""
Storage Resource
"""
uuid = models.UUIDField(verbose_name=_('UUID'), unique=True, default=uuid.uuid1, editable=False)
server = models.ForeignKey(Server, models.PROTECT, related_name="storages", related_query_name="storage", verbose_name=_('server'))
project = models.ForeignKey(Project, models.PROTECT, related_name="storages", related_query_name="storage", verbose_name=_('project'))
space_used_latest_copy = models.PositiveSmallIntegerField(_('space used latest copy'), db_index=True)
space_used_repository = models.PositiveSmallIntegerField(_('space used repository'), db_index=True)
space_used_other = models.PositiveSmallIntegerField(_('space used other'), db_index=True)
class Meta:
verbose_name = _('storage resource')
verbose_name_plural = _('storage resources')
unique_together = (('server', 'project'),)
ordering = ['server', 'project']
def __str__(self):
return f'{self.uuid} ({self.project}/{self.server})'
def get_space_used_total(self):
return self.space_used_latest_copy + self.space_used_repository + self.space_used_other

数据中心可以有许多服务器。从存储模型中,我可以得到服务器上使用了多少空间。

我需要获得数据中心最可用空间的服务器(只有一个(。

以下是目前的情况:

servers = Server.objects.all() 
.annotate(free=F('useful_storage_capacity') - Coalesce(Sum('storage__space_used_latest_copy'), V(0)) - Coalesce(Sum('storage__space_used_repository'), V(0))
- Coalesce(Sum('storage__space_used_other'), V(0))) 
.filter(free__gte=space_prepaid) 
.order_by('-free') 

我注释包含服务器可用空间的字段"空闲"。我需要以某种方式按数据中心对其进行分组并获得免费的最大价值。所以最后我从每个数据中心得到一个和最免费的服务器。

找不到任何示例如何以正确的方式进行操作。解决方案是什么?

谢谢!

您需要使用valuesvalues_list进行 GROUP BY 查询。

servers = Server.objects.all() 
.values('datacenter__uuid', 'id') 
.annotate(free=F('useful_storage_capacity') - Coalesce(Sum('storage__space_used_latest_copy'), V(0)) - Coalesce(Sum('storage__space_used_repository'), V(0))
- Coalesce(Sum('storage__space_used_other'), V(0))) 
.annotate(max_free=Max(F('free'))
.filter(free__gte=space_prepaid, free=F('max_free')) 
.values('datacenter__uuid', 'id', 'free')
.order_by('-free') 

我认为这应该为每个数据中心提供最免费的服务器。.values.filter.annotate的排序很重要,所以这可能会变得有点棘手。尝试使用这些方法。

最新更新