Using the Django DateQuerySet
I'm pulling related years for item
objects from a Group
query.
>>> Group.objects.all().dates('item__date', 'year')
[datetime.date(1990, 1, 1), datetime.date(1991, 1, 1), ...(remaining elements truncated)...']
Now I want to perform a count by distinct year on these dates. I thought this would work:
>>> Group.objects.all().dates('item__date', 'year').annotate(Count('year'))
FieldError: Cannot resolve keyword 'year' into field.
But looks like I'm missing something. How can I fix this query?
I've also tried this query:
>>> (Group
.objects
.all()
.extra(select=
{'year':
connections[Group.objects.db].ops.date_trunc_sql('year', 'app_item.date')}))
ProgrammingError: missing FROM-clause entry for table "app_item" LINE 1: SELECT (DATE_TRUNC('year', app_item.date)) AS...
But that doesn't work either.
-
Possible duplicate of Django: Group by date (day, month, year)tback– tback2016年06月24日 07:27:45 +00:00Commented Jun 24, 2016 at 7:27
2 Answers 2
For anyone finding this after django 1.9 there is now a TruncDate
(TruncMonth
, TruncYear
) that will do this.
from django.db.models.functions import TruncDate
(Group.objects.all().annotate(date=TruncDate('your_date_attr')
.values('date')
.annotate(Count('items'))
Hope it helps.
-
3@mycroft from what I can see, this was added in 1.10Ian Clark– Ian Clark2016年11月03日 16:32:45 +00:00Commented Nov 3, 2016 at 16:32
-
indeed - thanks @IanClark docs.djangoproject.com/en/1.10/ref/models/database-functions/…ptim– ptim2017年07月19日 16:13:27 +00:00Commented Jul 19, 2017 at 16:13
-
Should you use this, or Extract? docs.djangoproject.com/en/4.0/ref/models/database-functions/…gabn88– gabn882022年07月25日 16:35:43 +00:00Commented Jul 25, 2022 at 16:35
Try something along these lines:
from django.db.models import Count
Item.objects.all().\
extra(select={'year': "EXTRACT(year FROM date)"}).\
values('year').\
annotate(count_items=Count('date'))
You might want to use item_instance._meta.fields
instead of manually specifying "date" in the MySQL statement there...
Also, note that I started with Item
QuerySet instead of Group
, for the sake of simplicity. It should be possible to either filter the Item
QuerySet to get the desired result, or to make the extra
bit of MySQL more complicated.
EDIT:
This might work, but I'd definitely test the guts out of it before relying on it :)
Group.objects.all().\
values('item__date').\
extra(select={'year': "EXTRACT(year FROM date)"}).\
values('year').\
annotate(count=Count('item__date'))
-
Well, the
Group
query is what makes this interesting. I'm already doing other stuff related to it, so I can't just start from theItem
.Yuval Adam– Yuval Adam2014年02月17日 21:43:45 +00:00Commented Feb 17, 2014 at 21:43 -
Same error "missing FROM-clause entry for table..."Yuval Adam– Yuval Adam2014年02月17日 22:16:41 +00:00Commented Feb 17, 2014 at 22:16
-
Can you post your models? I have this working on a simple case with no such error.frnhr– frnhr2014年02月17日 23:55:20 +00:00Commented Feb 17, 2014 at 23:55
-
My models are slightly complicated, but I'm happy to hear it works for you. I'll see if I can get it to work on my side. Thanks!Yuval Adam– Yuval Adam2014年02月18日 08:32:38 +00:00Commented Feb 18, 2014 at 8:32
-
This doesn't work. It groups by date field but not by year.Andrii Zarubin– Andrii Zarubin2016年05月18日 04:56:13 +00:00Commented May 18, 2016 at 4:56
Explore related questions
See similar questions with these tags.