Решение для фильтрации по кумулятивной сумме и ошибке: Окно запрещено в условии фильтрации
Это продолжение вопроса к:
Фильтр запросов, сумма полей суммы которых больше или меньше числа
которая должна быть решена. В ответе предлагается использовать функцию Window с фильтром, но это приводит к ошибке:
django.db.utils.NotSupportedError: Window is disallowed in the filter clause.
В комментарии от @atabak hooshangi предлагается удалить функцию Window, но после этого запрос не работает в нужном виде. Есть идеи по решению этой проблемы?
Допустим, у нас есть эти 2 модели:
class Developer(models.Model):
first_name = models.CharField(max_length=40, null=False, blank=False,
unique=True)
last_name = models.CharField(max_length=40, null=False, blank=False,
unique=True)
profession = models.CharField(max_length=100, null=False)
cv = models.FileField(upload_to=upload_cv_location, null=True, blank=True)
description = models.TextField()
img = models.ImageField(upload_to=upload_location, null=True, blank=True)
class Meta:
verbose_name = 'Developer'
verbose_name_plural = 'Developers'
ordering = ('first_name',)
def __str__(self):
return f'{self.first_name} {self.last_name}'
class Skill(models.Model):
developer = models.ForeignKey(to=Developer, on_delete=models.CASCADE)
category = models.ForeignKey(to=SkillCategory, on_delete=models.SET_NULL,
null=True)
name = models.CharField(max_length=50, null=False)
priority = models.PositiveIntegerField()
class Meta:
ordering = ('-priority',)
def __str__(self):
return f'{self.name} skill of {self.developer}'
Как вы можете видеть, у нас есть модель разработчика, которая имеет связь с навыком. Каждый разработчик может иметь несколько навыков.
Теперь рассмотрим, что мы хотим получить разработчиков, сумма приоритетов которых больше некоторого числа.
Запрос orm должен работать следующим образом :
from django.db.models import Sum
developers = Developer.objects.annotate(tot=Sum('skill__priority')).filter(tot__gt=250).all()
На выходе будут разработчики, у которых priority_sum больше 250 .
Вы можете фильтровать tot, который является аннотированной переменной, любым удобным для вас способом.
подобно .filter(tot__lte)
или
.filter(tot__lt)
Надеюсь, это то, что вы искали.