I have a problem with django queryset ordering.
My model contains a field named position
(a PositiveSmallIntegerField), which I'd like to used to order query results.
I use order_by('position')
, which works great.
Problem : my position
field is nullable (null=True, blank=True
), because I don't wan't to specify a position for every 50000 instances of my model :(
When some instances have a NULL "position", order_by
returns them in the top of the list : I'd like them to be at the end...
In RAW SQL, I used to write things like "IF(position IS NULL or position='', 1, 0)
" (see http://www.shawnolson.net/a/730/mysql-sort-order-with-null.html) : is it possible to get the same result using Django, without writing raw SQL ?
Thanks very much !
I found that the syntax in Pablo's answer needed to be updated to the following on my 1.7.1 install:
QuerySet.extra()
can be used to inject expressions into the query and order by them.You can use the annotate() from django agrregation to do the trick:
Using extra() as Ignacio said optimizes a lot the end query. In my aplication I've saved more than 500ms (that's a lot for a query) in database processing using extra() instead of annotate()
Here is how it would look like in your case:
{tablename} should be something like {Item's app}_item following django's default tables name.
As of Django 1.8 you can use
Coalesce()
to convertNULL
to0
.Sample:
It's a shame there are a lot of questions like this on SO that are not marked as duplicate. See (for example) this answer for the native solution for Django 1.11 and newer. Here is a short excerpt:
Example usage (from comment to that answer):
Credit goes to the original answer author and commenter.