Решение для фильтрации по кумулятивной сумме и ошибке: Окно запрещено в условии фильтрации

Это продолжение вопроса к:

Фильтр запросов, сумма полей суммы которых больше или меньше числа

которая должна быть решена. В ответе предлагается использовать функцию 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)

Надеюсь, это то, что вы искали.

Вернуться на верх