Estoy tratando de contar las fechas en que los usuarios se registran desde un campo DateTime. En la base de datos, esto se almacena como '2016-10-31 20:49:38' pero solo me interesa la fecha '2016-10-31'.
La consulta SQL sin procesar es:
select DATE(registered_at) registered_date,count(registered_at) from User where course='Course 1' group by registered_date;Es posible usar 'extra' pero he leído que esto está en desuso y no debería hacerse. Sin embargo, funciona así:
User.objects.all() .filter(course='Course 1') .extra(select={'registered_date': "DATE(registered_at)"}) .values('registered_date') .annotate(**{'total': Count('registered_at')})¿Es posible hacerlo sin usar extra?
Leí que se puede usar TruncDate y creo que este es el conjunto de consultas correcto, sin embargo, no funciona:
User.objects.all() .filter(course='Course 1') .annotate(registered_date=TruncDate('registered_at')) .values('registered_date') .annotate(**{'total': Count('registered_at')}) Obtengo <QuerySet [{'total': 508346, 'registered_date': None}]> por lo que hay algo que va mal con TruncDate.
Si alguien entiende esto mejor que yo y puede indicarme la dirección correcta, se lo agradecería mucho.
Gracias por tu ayuda.
Estaba tratando de hacer algo muy similar y estaba teniendo los mismos problemas que tú. Logré que mi problema funcionara agregando una cláusula order_by después de aplicar la anotación TruncDate . Así que me imagino que esto también debería funcionar para ti:
User.objects.all() .filter(course='Course 1') .annotate(registered_date=TruncDate('registered_at')) .order_by('registered_date') .values('registered_date') .annotate(**{'total': Count('registered_at')})¡¿Espero que esto ayude?!
Esta es una alternativa a usar TruncDate usando `registered_at__date' y Django hace el truncamiento por ti.
from django.db.models import Count from django.contrib.auth import get_user_model metrics = { 'total': Count('registered_at__date') } get_user_model().objects.all() .filter(course='Course 1') .values('registered_at__date') .annotate(**metrics) .order_by('registered_at__date')Para Postgresql esto se transforma en la consulta DB:
SELECT ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date, COUNT("auth_user"."registered_at") AS "total" FROM "auth_user" GROUP BY ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date ORDER BY ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date ASC; En el ejemplo anterior, puede ver que Django ORM invierte los argumentos SELECT y GROUP_BY . En Django ORM .values() controla aproximadamente el argumento GROUP_BY mientras que .annotate() controla las columnas SELECT y qué agregaciones deben realizarse. Esto se siente un poco extraño, pero es simple cuando le coges el truco.