Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django - reorder queryset after slicing it

I fetch the latest 5 rows from a Foo model which is ordered by a datetime field.

qs = Foo.objects.all()[:5]

In the following step, I want to reorder the queryset by some other criteria (actually, by the same datetime field in the opposite direction). But reordering after a slice is not permitted. reverse() undoes the first ordering, giving me a differet queryset. Is there a way to accomplish what I want without creating a list from the queryset and doing the ordering using it?

like image 972
shanyu Avatar asked Jun 02 '09 11:06

shanyu


2 Answers

order_by gives you SQL in-database ordering. You're already using that, and then slicing on it. At that point, the results are retrieved into memory. If you want to change their order, you need to use Python in-memory sorting to do it, not the ORM in-database sorting.

In your case, Daniel has already given the best solution: since you simply want to sort by the same field, but in the other order, just reverse the list you have:

qs = Foo.objects.all()[:5]
objs = reversed(qs)

If you had wanted to sort by some other field, then you'd use the sorted() function with a custom key function:

qs = Foo.objects.all()[:5]
objs = sorted(qs, key=lambda o: o.some_other_field)
like image 152
Ned Batchelder Avatar answered Nov 07 '22 06:11

Ned Batchelder


No, there's no way of doing that. order_by is an operation on the database, but when you slice a queryset it is evaluated and doesn't go back to the database after that.

Sounds like you already know the solution, though: run reversed() on the evaluated qs.

qs = reversed(Foo.objects.all()[:5])
like image 26
Daniel Roseman Avatar answered Nov 07 '22 05:11

Daniel Roseman