Dan
Dan

Reputation: 43

Django - Sort Queryset by Date instead of Datetime

I have a model (representing a 'job') that contains a DateTimeField called date_created. I have another called date_modified.

I would like to sort by -date_modified so that the most recently modified 'jobs' are at the top of my list. The problem is that multiple running jobs will keep getting reordered each time the timestamp gets updated. If the date_modified field was sorted as if it was a DateField, then I could sort all 'jobs' that have been modified 'today' first, and then sort off of a second value (like date_created) so that they would not change places in the list as the timestamps are modified.

This is what I have now:

queryset = DataCollection.objects.all().order_by('-date_modified','-date_created')

I found a related article, but seems outdated with version 1.9: Django sorting by date(day)

UPDATE

The current fix that I am looking at is this:

queryset = DataCollection.objects.all().extra(select = 
{'custom_dt': 'date(date_modified)'}).order_by('-custom_dt','-date_created')

It's most similar to what @lampslave was suggesting, but it uses the extra method, which will be deprecated in the future... I don't think that I will be upgrading to a later version of Django anytime soon, but this makes my stomache a bit unsettled.

Upvotes: 2

Views: 2978

Answers (3)

davidejones
davidejones

Reputation: 1949

I think souldeux answer is probably a lot neater than this but another solution could be to query separately then join them together. I think something along these lines

from itertools import chain
import datetime

# get just todays data ordered by date modified
today_min = datetime.datetime.combine(datetime.date.today(), datetime.time.min)
today_max = datetime.datetime.combine(datetime.date.today(), datetime.time.max)
data_set1 = DataCollection.objects.filter(date_modified__range=(today_min, today_max)).order_by('-date_modified')

# get the rest of the data
data_set2 = DataCollection.objects.all().exclude(date_modified__range=(today_min, today_max)).order_by('-date_created')

# join it all together
all_list = list(chain(data_set1, data_set2))

I think django had planned to introduce a __date query selector i don't know if that is available yet but that might also help

Upvotes: 0

lampslave
lampslave

Reputation: 1513

If your database supports datetime_to_date converting, you can try something like this:

DataCollection.objects.all().annotate(date_created__date=RawSQL('DATE(date_created)', ())).order_by('-date_created__date')

Upvotes: 0

souldeux
souldeux

Reputation: 3755

I would get the queryset then sort it in the view in this case.

sorted(DataCollection.objects.all(), key = lambda x: x.date_modified.date(), reverse = True)

To sort by two keys you can use attrgetter, described in the HowTo/Sorting docs.

Upvotes: 2

Related Questions