Formatting dates for annotating count in Django + Python 3
Asked Answered
K

1

7

I'm currently trying to annotate and count some dates, based on the number of times they appear.

visits = Subs.objects.filter(camp=campdata, timestamp__lte=datetime.datetime.today(), timestamp__gt=datetime.datetime.today()-datetime.timedelta(days=30)).\
values('timestamp').annotate(count=Count('timestamp'))

If I print this in a for loop like,

for a in visits:
  print(a)

I would get back the following in Json.

{'timestamp': datetime.datetime(2018, 10, 5, 15, 16, 25, 130966, tzinfo=<UTC>), 'count': 1}
{'timestamp': datetime.datetime(2018, 10, 5, 15, 16, 45, 639464, tzinfo=<UTC>), 'count': 1}
{'timestamp': datetime.datetime(2018, 10, 6, 8, 43, 24, 721050, tzinfo=<UTC>), 'count': 1}
{'timestamp': datetime.datetime(2018, 10, 7, 4, 54, 59, tzinfo=<UTC>), 'count': 1}

This is kinda the right direction, however, it's counting to the second.. I just need to days, so that the event that happened on 2018, 10, 5 would be count: 2 for example.

Can anyone lead me into the right direction?

Additionally, whats the most "django" way of converting the dates into something more json / api friendly?

My ideal json return would be something like

{'timestamp': 2018-10-5, 'count': 2}

Thanks!

Killarney answered 7/10, 2018 at 9:31 Comment(0)
Z
9

You can use the TruncDate annotation to achieve this:

visits = Subs.objects.annotate(date=TruncDate('timestamp')).filter(
    camp=campdata, 
    date__lte=datetime.datetime.today(), 
    date__gt=datetime.datetime.today() - datetime.timedelta(days=30)
).values('date').annotate(count=Count('date'))

As for your question about serializing dates for JSON, Django provides the DjangoJSONEncoder to help with just that:

import json
from django.core.serializers.json import DjangoJSONEncoder

json.dumps(list(visits), cls=DjangoJSONEncoder)
Zurkow answered 7/10, 2018 at 11:41 Comment(2)
awesome! Truncdate worked fantastic! I now get the queryset <QuerySet [{'date': datetime.date(2018, 10, 5), 'count': 2}, {'date': datetime.date(2018, 10, 6), 'count': 1}, {'date': datetime.date(2018, 10, 7), 'count': 1}]> I am however still having issues with the serializing AttributeError: 'dict' object has no attribute '_meta'Killarney
Looks like serialize only works on model querysets - I've edited the answer to use json.dumps() instead, which should hopefully work.Zurkow

© 2022 - 2024 — McMap. All rights reserved.