24

Let's say I have a queryset of things Bill has worked on like this:

test=Things.objects.filter(user='Bill')

Now I want to sort all those things by the date they were assigned to bill. Unfortunately the assignment date isn't a field in the Thing model. Instead there's a method named thing_date() that figures it out and returns the date. For example, the following:

Thingobject.thing_date()

...returns the date. I guess what I want to do is something like:

test=Things.objects.filter(user='Bill').order_by(self__thing_date())

...but I know that won't work. Is there another way?

Update

Not surprisingly other folks have been down this road before. Link

Community
  • 1
  • 1
James M
  • 373
  • 1
  • 2
  • 9

2 Answers2

31

If thing_date() is a function in python code, you can't get the database to sort on it. Which means it doesn't make sense to put the queryset. You'll have to sort the results after you get them into python. This will be fine so long as you're not dealing with a very large number of objects.

qs = Things.objects.filter(user='Bill')
unsorted_results = qs.all()
sorted_results = sorted(unsorted_results, key= lambda t: t.thing_date())

If you've got a very large number of Things then you'll have to figure some way to get thing_date into the database or else you'll have memory issues.

Leopd
  • 41,333
  • 31
  • 129
  • 167
  • Well, that gets things in the proper order but it breaks some code further down that's written to work with a queryset. But that's a separate problem. Thanks for the answer. – James M Aug 04 '11 at 14:01
16

see these answers to use a computed value to sort a QuerySet:

Basically if thing_date() can be determined using a query expression, then you can use it to annotate and search the query set.

from django.db.models import F
from django.utils import timezone
test = Things.objects.filter(user='Bill').annotate(
    thing_date=(F('<date field>') - timezone.now())  # some computation
).order_by('thing_date')
Community
  • 1
  • 1
Mark Mikofski
  • 19,398
  • 2
  • 57
  • 90