我有三个模型。
数据中心
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')
我注释包含服务器可用空间的字段"空闲"。我需要以某种方式按数据中心对其进行分组并获得免费的最大价值。所以最后我从每个数据中心得到一个和最免费的服务器。
找不到任何示例如何以正确的方式进行操作。解决方案是什么?
谢谢!
您需要使用values
或values_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
的排序很重要,所以这可能会变得有点棘手。尝试使用这些方法。