2014-02-20 2 views
0

Я ищу получение QuerySet, отсортированного по полю1, функции, field2.Как сортировать Django QuerySet по (поле, пользовательская функция, поле)

Модель:

class Task(models.Model): 
    issue_id = models.CharField(max_length=20, unique=True) 
    title = models.CharField(max_length=100) 
    priority_id = models.IntegerField(blank=True, null=True) 
    created_date = models.DateTimeField(auto_now_add=True) 

    def due_date(self): 
     ... 
     return ageing 

Я ищу что-то вроде:

taskList = Task.objects.all().order_by('priority_id', ***duedate***, 'title') 

Очевидно, что вы не можете сортировать QuerySet по пользовательской функции. Есть рекомендации?

ответ

2

Поскольку фактическая сортировка происходит в базе данных, которая не говорит на Python, вы не можете использовать функцию Python для упорядочения. Вам нужно будет реализовать из-за логики дат в выражении SQL, как Queryset.extra(select={...}) вычисляется поле, что-то вдоль линий:

due_date_expr = '(implementation of your logic in SQL)' 
taskList = Task.objects.all().extra(select={'due_date': due_date_expr}).order_by('priority_id', 'due_date', 'title') 

Если ваша логика слишком сложна, возможно, потребуется реализовать его в качестве хранимой процедуры в вашей базе данных.

В качестве альтернативы, если ваш набор данных очень мало (скажем, от десятков до нескольких сотен записей), вы можете получить весь набор результатов в виде списка и сортировать его постфактум:

taskList = list(Task.objects.all()) 
taskList.sort(cmp=comparison_function) // or .sort(key=key_function) 
+0

Хороший ответ. Поэтому он должен либо обрабатываться в конце SQL, либо в конце Python. – killua8p

0

Вы можете использовать сортировку в Python, если набор запросов не слишком велик:

ordered = sorted(Task.objects.all(), key=lambda o: (o.priority_id, o.due_date(), o.title)) 
+0

спасибо за ответ. но это не станет order_by (duedate, title) - без priority_id? – killua8p

+0

Хорошая точка. Я исправил свой ответ. – arocks

Смежные вопросы