Итак, чтобы сделать пример использования более конкретным:
Сессии присоединяются к пользователям через отношения «усилия».Учитывая время начала и окончания, я хотел отобразить список для пользователей с указанием количества сессий - с датой между датой начала и окончания - прикрепленной к ним.Сессии далее идентифицируются веткой.Это то же самое для пользователей, однако пользователи могут принадлежать к нескольким веткам.Следовательно, счетчик должен быть дополнительно детализирован, чтобы принимать только сеансы в счетчик с ветвью, которая появляется в ветвях для пользовательского объекта запросчиков.Кроме того, пользователи с числом сеансов, равным нулю, должны быть опущены, чтобы сохранить результат кратким.
Модель сеанса выглядит следующим образом:
class Session(models.Model):
date = models.DateTimeField(default=now, blank=False)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='efforts', on_delete=models.CASCADE)
branch = models.ForeignKey(Branch, related_name='hour_branch', on_delete=models.CASCADE)
status = models.IntegerField(default=1, blank=False, validators=[MinValueValidator(0), MaxValueValidator(3)])
Модель пользователя выглядит следующим образом (пропущено)различные поля для краткости).
class User(AbstractUser):
branches = models.ManyToManyField(Branch)
Ответ выше был неудовлетворительным, так как он не позволял мне фильтровать сеансы, которые учитываются для пользователя по желанию.Поэтому я и выбрал следующее решение, используя условное выражение :
Код для рассматриваемого представления:
class AggregateSessionList(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSessionsSerializer
permission_classes = (permissions.IsAdminUser,)
def get_queryset(self):
today=datetime.date.today()
month=self.request.query_params.get('month', today.month)
year=self.request.query_params.get('year', today.year)
start = datetime.date(year=year, month=month, day=1)
end = datetime.datetime(year=start.year + int(start.month / 12), month=int((start.month % 12) + 1), day=1)
branches = self.request.user.branches.all()
return User.objects.annotate(
sessions=Count(Case(
When(efforts__date__gt=start, efforts__date__lt=end, efforts__branch__in=branches, then=1),
output_field=IntegerField()))).filter(sessions__gt=0)
Код для сериализатора:
class UserSessionsSerializer(serializers.ModelSerializer):
sessions = serializers.IntegerField()
class Meta:
model = User
fields = ('username', 'sessions')
Думал, что поделюсь этим решением, поскольку не могу найти ничего похожего.
РЕДАКТИРОВАТЬ
Дополнительным преимуществом этого решения в пользу ответа Руддры является то, чтовыполняется только один запрос к БД.Это в отличие от ответа Руддры, где для каждого пользователя выполняется дополнительный запрос (что не представляется возможным для моих требований).