¿Cómo ejecutar un GROUP BY … COUNT o SUM en Django ORM?

Prólogo:

Esta es una pregunta que surge a menudo en SO:

  • Django Models Group By
  • Django equivalente para contar y agrupar por
  • ¿Cómo consultar como GROUP BY en django?
  • ¿Cómo utilizar el ORM para el equivalente de un recuento de SQL, un grupo y una consulta de unión?

He compuesto un ejemplo en la Documentación SO, pero como la Documentación se cerrará el 8 de agosto de 2017, seguiré la sugerencia de esta meta-respuesta ampliamente comentada y comentada, y transformaré mi ejemplo en una publicación auto contestada.

Por supuesto, también me encantaría ver cualquier enfoque diferente.


Pregunta:

Supongamos el modelo:

class Books(models.Model): title = models.CharField() author = models.CharField() price = models.FloatField() 

¿Cómo puedo realizar las siguientes consultas en ese modelo utilizando Django ORM?

  • GROUP BY ... COUNT :

     SELECT author, COUNT(author) AS count FROM myapp_books GROUP BY author 
  • GROUP BY ... SUM :

     SELECT author, SUM (price) AS total_price FROM myapp_books GROUP BY author 

Podemos realizar un GROUP BY ... COUNT o GROUP BY ... SUM consultas equivalentes de SQL en Django ORM, con el uso de annotate() , values() , los django.db.models Count y Sum django.db.models respeto y opcionalmente el método order_by() :

  • GRUPO POR … CUENTA:

     result = Books.objects.values('author') .order_by('author') .annotate(count=Count('author')) 

    Ahora el resultado contiene un diccionario con dos claves: author y count :

      author | count ------------|------- OneAuthor | 5 OtherAuthor | 2 ... | ... 
  • GRUPO POR … SUM:

      result = Books.objects.values('author') .order_by('author') .annotate(total_price=Sum('price')) 

    Ahora el resultado contiene un diccionario con dos columnas: author y total_price :

      author | total_price ------------|------------- OneAuthor | 100.35 OtherAuthor | 50.00 ... | ...