#python #django #django-models
#python #django #django-модели
Вопрос:
У меня есть 100 тысяч записей в день, и я использую их для вывода в API (у меня есть ограничение и смещение по умолчанию). Я хочу вычислить значения в моем наборе запросов, если у них есть общий owner_id, и оставить остальное как есть, если нет общего владельца для дельты даты
То, что я делаю сейчас, но не выглядит правильным (он правильно вычисляет некоторые данные, но по какой-то причине некоторые данные также увеличиваются, чего не должно было быть)
TrendData.objects.filter(owner__trend_type__mnemonic='posts').filter(
date_trend__date__range=[date_from, date_to]).values('owner__name').annotate(
views=(Sum('views') / date_delta),
views_u=(Sum('views_u') / date_delta),
likes=(Sum('likes') / date_delta),
shares=(Sum('shares') / date_delta),
interaction_rate=(
Sum('interaction_rate') / date_delta),
)
date_delta = date_to - date_from #<- integer
мои модели:
class Owner(models.Model):
class Meta:
verbose_name_plural = 'objects'
TREND_OWNERS = Choices('group', 'user')
link = models.CharField(max_length=255)
name = models.CharField(max_length=255)
owner_type = models.CharField(choices=TREND_OWNERS, max_length=50)
trend_type = models.ForeignKey(TrendType, on_delete=models.CASCADE)
def __str__(self):
return f'{self.link}[{self.trend_type}]'
class TrendData(models.Model):
class Meta:
verbose_name_plural = 'Trends'
owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
views = models.IntegerField()
views_u = models.IntegerField()
likes = models.IntegerField()
shares = models.IntegerField()
interaction_rate = models.DecimalField(max_digits=20, decimal_places=10)
mean_age = models.IntegerField()
source = models.ForeignKey(TrendSource, on_delete=models.CASCADE)
date_trend = models.DateTimeField()
Исходная родительская модель в этом случае на самом деле не помогает, это csv-файл, из которого были загружены данные, поэтому мы никогда не ссылаемся на него.
Я хочу, возможно ли вычислить сумму, views, views_u, likes, shares, interaction_rate
если owner
выполняется для обоих дней (скажем, с 01.01.19 по 10.01.2019), и если в оба дня есть 2 владельца, вычислите сумму, если не пропустите, и оставьте ее как простой набор запросов без суммирования ВСЕХ значений в нем, еслизатем вычислите и оставьте остальное как есть. Я могу сделать это с помощью python, но я думаю, что это можно сделать в django ORM
Ответ №1:
Django ORM предоставляет условные выражения для выполнения такого рода аннотаций на основе условий. Вы можете использовать Case
для аннотирования на Sum
основе упомянутого вами условия.
TrendData.objects.filter(owner__trend_type__mnemonic='posts').annotate(
views=Sum(
Case(
When("Your condition here", then=F('views')),
default=0,
output_field=IntegerField(),
)
)
...
)