Tengo un modelo simple como este:
class Order(models.Model):
created = model.DateTimeField(auto_now_add=True)
total = models.IntegerField() # monetary value
Y quiero generar un desglose mes a mes de:
- Cuantas ventas hubo en un mes (
COUNT
) - El valor combinado (
SUM
)
No estoy seguro de cuál es la mejor manera de atacar esto. He visto algunas consultas de selección extra que parecen bastante aterradoras, pero mi mente simple me dice que podría estar mejor simplemente iterando números, comenzando desde un año / mes de inicio arbitrario y contando hasta llegar al mes actual, descartando simples filtrado de consultas para ese mes. Más trabajo de base de datos, ¡menos estrés del desarrollador!
¿Qué tiene más sentido para ti? ¿Existe una buena forma de recuperar una tabla rápida de datos? ¿O mi método sucio es probablemente la mejor idea?
Estoy usando Django 1.3. No estoy seguro de si han agregado una forma más agradable GROUP_BY
recientemente.
Respuestas:
Django 1.10 y superior
Listas de documentación de Django
extra
como obsoleta en poco tiempo . (Gracias por señalar eso @seddonym, @ Lucas03). Abrí un boleto y esta es la solución que proporcionó jarshwah.versiones mas antiguas
Ediciones
fuente
>>> qs.extra({'month':td}).values('month').annotate(Sum('total')) [{'total__sum': Decimal('1234.56'), 'month': datetime.datetime(2011, 12, 1, 0, 0)}]
'{}.timestamp'.format(model._meta.db_table)
USE_TZ
configuración de Django esTrue
, las dos versiones no son exactamente equivalentes. La versión que usaTruncMonth
convertirá la marca de tiempo a la zona horaria especificada por laTIME_ZONE
configuración antes de truncar, mientras que la versión que usadate_trunc_sql
truncará la marca de tiempo UTC sin procesar en la base de datos.Solo una pequeña adición a la respuesta de @tback: no funcionó para mí con Django 1.10.6 y postgres. Agregué order_by () al final para arreglarlo.
fuente
TruncDate
le permite agrupar por fecha (día del mes)Otro enfoque es utilizar
ExtractMonth
. Tuve problemas al usar TruncMonth debido a que solo se devolvió un valor de año de fecha y hora. Por ejemplo, solo se devolvieron los meses de 2009. ExtractMonth solucionó este problema perfectamente y se puede usar como se muestra a continuación:fuente
El
queryset
es una lista de Orden, una línea por cada mes, la combinación de la suma de las ventas:sales_sum
@Django 2.1.7
fuente
Este es mi método sucio. Está sucio.
Bien puede haber una mejor manera de recorrer años / meses, pero eso no es lo que realmente me importa :)
fuente
Así es como puede agrupar datos por períodos de tiempo arbitrarios:
fuente
Por mes:
Por año:
Por día:
No olvide importar Count
Para django <1.10
fuente