Как сделать SELECT COUNT(*) GROUP BY для поля ForeignKey в Django?

Допустим, у нас есть три модели:

class Category(models.Model):
    name = models.CharField(max_length=255)

class Platform(models.Model):
    name = models.CharField(max_length=255)

class Product(models.Model):
    name = models.CharField(max_length=255)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products')
    platform = models.ForeignKey(Platform, on_delete=models.CASCADE, related_name='products')

class SellingItem(models.Model):
    name = models.CharField(max_length=255)
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='selling_items')
    price = models.DecimalField(max_digits=5, decimal_places=2)

Идея здесь заключается в том, чтобы получить сумму различных категорий и платформ на основе кверисета SellingItem.

Мой первоначальный подход таков:

categories = queryset.values('product__category__id', 'product__category__name', 'product__category__label').annotate(total=Count('product__category__id'))  # noqa: E501
platforms = queryset.exclude(product__platform__isnull=True).values('product__platform__id', 'product__platform__name', 'product__platform__label').annotate(total=Count('product__platform__id'))  # noqa: E501

Проблема в том, что результат не группируется...

Код работает на основе кверисета Product, если удалить все product__ в предыдущем коде.

Ваш подход к проблеме абсолютно правильный. Хотя вам не хватает небольшой детали в конце - '.order_by()'. Если вы добавите его, то получите желаемый результат. Это означает, что django не будет применять любой тип упорядочивания. Таким образом, вы достигнете желаемого результата.

Эта проблема возникла из-за того, что django пытался применить упорядочивание по умолчанию, которое у него есть, поэтому ваш набор запросов не выдал желаемых результатов.

Надеюсь, это вам поможет!

categories = queryset.values('product__category__id', 'product__category__name', 'product__category__label').annotate(total=Count('product__category__id')).order_by()  # order_by at the end.
platforms = queryset.exclude(product__platform__isnull=True).values('product__platform__id', 'product__platform__name', 'product__platform__label').annotate(total=Count('product__platform__id')).order_by()  # order_by at the end.
Вернуться на верх