Вы можете подойти к нему, воспользовавшись атрибутом related_name
полей ForeignKey
в Django и стандартным декоратором 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
модели:
class Channel(models.Model):
...
@property
def num_of_recordings(self):
return self.recordings.count()
# __________^ (related_name)
Теперь для вашего storage_size
вы можете агрегировать его с помощью aggregate()
метод QuerySet
и Sum
функция агрегирования:
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
, они только для чтения по своей конструкции и, таким образом, рассчитываются динамически на основе соответствующих записей.