我有几个Django模型,即Channel和Recording。通道与记录具有一对多的关系,因此一个通道可能具有许多记录。在Channel模型中,我目前有2个字段num_recordings和storage_size,它们现在被创建为Integers,但是我想作为数据库查询的结果动态生成。例如。 num_recordings应该是给定通道上当前记录的计数,而storage_size应该是给定通道上每个记录的字段“ size”的总和。
我正在使用Django rest框架提供模型的JSON表示,并希望在查询Channel时看到这两个字段为Integers,但又不想分别计算它们,例如如果查询Channel端点时,它将对记录关系进行计数,然后将其作为“ num_recordings”返回,并在该关系中的所有记录的recording.size字段中返回一个总和,并在storage_size中报告该计数,则将是理想的领域。
我该怎么做?
答案 0 :(得分:1)
您可以通过受益于Django中related_name
字段的ForeignKey
属性和标准Python @property
装饰器来实现它。
首先,假设您已经在models.py
中定义了这样的关系:
class Channel(models.Model):
...
class Recording(models.Model):
channel = models.ForeignKey(Channel, on_delete=..., related_name='recordings')
# ________________________________________________________________^
# This is the reverse relation name, e.g. channel.recordings
从现在开始,您可以从recordings
本身访问特定channel
的相关channel
:
>>> channel = Channel.objects.create(...)
>>> recording1 = Recording.objects.create(channel=channel, ...)
>>> recording2 = Recording.objects.create(channel=channel, ...)
>>> channel.recordings.all()
<QuerySet [<Recording: 1>, <Recording: 2>]>
>>> channel.recordings.count()
2
您可以在Channel
模型中直接使用those methods:
class Channel(models.Model):
...
@property
def num_of_recordings(self):
return self.recordings.count()
# __________^ (related_name)
现在为您的storage_size
,您可以通过QuerySet
的{{3}}方法和aggregate()
聚合函数对其进行聚合:
from django.db.models import Sum
class Channel(models.Model):
...
@property
def storage_size(self):
return self.recordings.aggregate(storage_size=Sum('size'))['storage_size']
现在是最终的Channel
模型:
class Channel(models.Model):
...
@property
def num_of_recordings(self):
return self.recordings.count()
@property
def storage_size(self):
return self.recordings.aggregate(storage_size=Sum('size'))['storage_size']
最后一步是在您的通道序列化器类中添加这些新属性num_of_recordings
和storage_size
以便显示它们。由于它们以@property
装饰,因此它们在设计上是只读,因此会根据相关记录进行动态计算。