pedro lukas
pedro lukas

Reputation: 13

Group by in Django with field distinction

I have two tables, one for products and one for suppliers, I did a query that returns this:

select 
    f.nome, f.cnpj, sum(p.quantidade) as "Quantidade de Produtos", 
    count(distinct categoria_id) as "Categorias com Produtos "
from 
    core_produtos p
inner join 
    core_fornecedor f
on 
    p.fornecedor_id=f.id
group by 
    f.nome, f.cnpj
order by 
    f.nome ASC;

and she returns a table like this:

     nome     |        cnpj        | Quantidade de Produtos | Categorias com Produtos  
--------------+--------------------+------------------------+--------------------------
 fornecedor 1 | 10.331.608/0001-52 |                   7339 |                        5
 fornecedor 2 | 00.333.725/0001-00 |                   7673 |                        5
 fornecedor 3 | 88.550.421/0001-37 |                   8423 |                        5
 fornecedor 4 | 03.251.500/0001-94 |                  14101 |                        5
 fornecedor 5 | 25.862.630/0001-04 |                   8988 |                        5

my models in the tables involved:

class Produtos(models.Model):

    categoria = models.ForeignKey(
        Categoria, related_name="produtos", on_delete=models.CASCADE)
    fornecedor = models.ForeignKey(
        Fornecedor, related_name="fornecedores", on_delete=models.CASCADE, max_length=225)
    nome = models.CharField(max_length=255)
    descricao = models.TextField(blank=True)
    preco = models.DecimalField(max_digits=10, decimal_places=2)
    quantidade = models.IntegerField(default=0)
    disponivel = models.BooleanField(default=True)

    class Meta:
        verbose_name = "Produto"
        verbose_name_plural = "Produtos"

    def __str__(self):
        return self.nome
class Fornecedor(models.Model):

    nome = models.CharField(max_length=255)
    cnpj = models.CharField(max_length=20, unique=True)

    class Meta:
        verbose_name = "Fornecedo"
        verbose_name_plural = "Fornecedores"

    def __str__(self):
        return self.cnpj

my question is: how do I query using django's ORM?

Upvotes: 0

Views: 60

Answers (1)

qcoumes
qcoumes

Reputation: 517

You can achieve this using annotate() :

from django.db.models import Sum, Count

Fornecedor.objects.annotate(
    quantidade_de_produtos=Sum("fornecedores__quantidade"),
    categorias_com_produtos=Count("categoria__id", distinct=True),
).order_by("nome")

This will return a QuerySet in which each instance will have the attributes quantidade_de_produtos and categorias_com_produtos containing the results of the annotation.


The annotation are done on the quantidade field the Fornecedor table using lookup that span relationships. This is done using two underscores __to travel through relations (in this case fornecedores and quantidade, which are both ForeignKey).

Upvotes: 1

Related Questions