0
Model1(models.Model):
  name = models.CharField(max_length=30)


Model2(models.Model):
  model1 = models.ManyToManyField(FontClass) 

res = Model1.objects.all().filter(....).order_by('model1__name....???')

How can sort the result by more complex condition such whether or not model1__name has an underscore in its name? For example, Model1.objects.all().filter(....) returns the following names:

aaa_bbb
aaaccc
aaa_ttt
aaa_ddd
ggggg
yyy_cccc
zzz_kkk
dddd

After sorting it should be:

aaa_bbb
zzz_kkk
aaa_ddd
aaa_ttt
yyy_cccc

aaaccc
ggggg
dddd

First the ones with the underscore in their names, then - without it.

Note that condition is just an example for I want to be to sort by even complex ones, I just want to get how to do that.

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • You could split the results into two lists, and then alphabetically sort them. – rnevius May 26 '15 at 07:21
  • possible duplicate of [Custom ordering in Django](http://stackoverflow.com/questions/883575/custom-ordering-in-django) – Wtower May 26 '15 at 07:25
  • `Queryset.order_by()` relies on database ordering, IOW it just adds a SQL `order by` clause. So you can either try to setup your database to get the desired ordering or (if your typical dataset isn't too huge) go for a pure python sort but that might be way less efficient. – bruno desthuilliers May 26 '15 at 07:48

2 Answers2

0

How about just changing the compare function of a regular sort algorithm?

def comp(a, b):
    if a>b:
        return True

def mergeSort(alist):
    if len(alist)>1:
        mid = len(alist)//2
        lefthalf = alist[:mid]
        righthalf = alist[mid:]

        mergeSort(lefthalf)
        mergeSort(righthalf)

        i=0
        j=0
        k=0
        while i<len(lefthalf) and j<len(righthalf):
            if comp(righthalf[j], lefthalf[i]):
                alist[k]=lefthalf[i]
                i=i+1
            else:
                alist[k]=righthalf[j]
                j=j+1
            k=k+1

        while i<len(lefthalf):
            alist[k]=lefthalf[i]
            i=i+1
            k=k+1

        while j<len(righthalf):
            alist[k]=righthalf[j]
            j=j+1
            k=k+1

my_list = [10,4,2,5,1]
mergeSort(my_list)
print my_list

Just change the "comp" function to do what you want.

albf.unicamp
  • 159
  • 1
  • 5
0

You can use the extra method of the queryset to apply database sorting

Model1.objects.extra(
    select={'has_underscore': "position('_' in name) > 0"}, 
    order_by=['-has_underscore'])

Note that, you will be tied to a specific database. My example is working on postgresql.

Yossi
  • 11,778
  • 2
  • 53
  • 66