13

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.

Rob Bednark
28.6k28 gold badges90 silver badges131 bronze badges
asked Feb 17, 2014 at 19:03
1

2 Answers 2

30

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.

djvg
14.6k7 gold badges84 silver badges119 bronze badges
answered Sep 29, 2016 at 16:31
3
12

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'))
gregoltsov
2,3092 gold badges23 silver badges38 bronze badges
answered Feb 17, 2014 at 21:38
8
  • 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 the Item. Commented Feb 17, 2014 at 21:43
  • Same error "missing FROM-clause entry for table..." Commented Feb 17, 2014 at 22:16
  • Can you post your models? I have this working on a simple case with no such error. Commented 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! Commented Feb 18, 2014 at 8:32
  • This doesn't work. It groups by date field but not by year. Commented May 18, 2016 at 4:56

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.