2016-08-22 2 views
1

У меня есть модель (представляющая «работы»), который содержит DateTimeField называется DATE_CREATED. У меня есть еще один номер date_modified.Джанго - Сортировка по дате QuerySet вместо DATETIME

Я хотел бы сортировать по -date_modified, так что последние измененные «рабочие места» находятся в верхней части моего списка. Проблема в том, что несколько выполняемых заданий будут постоянно переупорядочиваться каждый раз, когда метка времени обновляется. Если поле date_modified было отсортировано так, как если бы оно было DateField, тогда я мог бы отсортировать все «задания», которые были изменены «сегодня», а затем отсортировать второе значение (например, date_created), чтобы они не меняйте места в списке с изменением временных меток.

Это то, что я сейчас:

queryset = DataCollection.objects.all().order_by('-date_modified','-date_created') 

Я нашел статью по теме, но кажется устаревшим с версии 1.9: Django sorting by date(day)

UPDATE

В настоящее время починки, что я рассматриваемый здесь:

queryset = DataCollection.objects.all().extra(select = 
{'custom_dt': 'date(date_modified)'}).order_by('-custom_dt','-date_created') 

Это наиболее похоже на то, что предлагал @lampslave, но он использует метод extra, который будет устаревать в будущем ... Я не думаю, что в ближайшее время я буду обновляться до более поздней версии Django, но это делает мою головную боль немного неустроенной.

+0

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

+0

Хорошая точка. Почему DateTimeField не содержит информацию о часовом поясе? – Dan

+0

Если вы работаете с датами времени, зависящими от часового пояса, то часовые пояса обычно считаются принадлежащими к слою презентации. DateTimes должен быть в UTC внутренне и преобразован как можно позже. См. Https://docs.djangoproject.com/en/1.10/topics/i18n/timezones/ –

ответ

2

Я бы получил запрос, затем отсортировал его в представлении в этом случае.

sorted(DataCollection.objects.all(), key = lambda x: x.date_modified.date(), reverse = True) 

Для сортировки двумя ключами, которые можно использовать attrgetter, описанных в HowTo/Сортировка документации.

+0

Это похоже на очень хороший способ сделать это, но у меня возникают проблемы с моей маршрутизацией Django DRF, дающей «no base_name», ошибка, поэтому пока, я пытаюсь сделать все это в самом запросе, потому что по какой-то причине я не могу вернуть список. – Dan

+1

Если вы в 1.10, вы можете что-то сделать с помощью Cast (https://docs.djangoproject.com/en/1.10/ref/models/database-functions/# cast) или с одной из новых функций даты (https://docs.djangoproject.com/en/1.10/ref/models/database-functions/#module-django.db .models.functions.datetime). Тем не менее, я нахожусь в 1.9.x по большей части, поэтому у меня нет практического опыта с ними. – souldeux

+0

Я использую 1,8 так, а несколько других вариантов вышли за дверь. Я думаю, что правильным ответом в будущем будет использование __date всякий раз, когда это станет доступным. – Dan

0

Если ваша база данных поддерживает datetime_to_date преобразования, вы можете попробовать что-то вроде этого:

DataCollection.objects.all().annotate(date_created__date=RawSQL('DATE(date_created)',())).order_by('-date_created__date') 
+0

Это выглядит почти правильно, но я чувствую, что есть чистый способ «Django», чтобы я не использовал Raw SQL-запросы. У всех db есть datetimefield -> преобразование даты? Должна ли Django иметь какой-либо способ сделать это под капотом, пока выставляете API для этого? – Dan

+0

Просмотреть комментарии для souldeux. Попробуйте использовать новые выражения или функции вместо RawSQL. – lampslave

+0

Что вы подразумеваете под «новыми выражениями» – Dan

0

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

from itertools import chain 
import datetime 

# get just todays data ordered by date modified 
today_min = datetime.datetime.combine(datetime.date.today(), datetime.time.min) 
today_max = datetime.datetime.combine(datetime.date.today(), datetime.time.max) 
data_set1 = DataCollection.objects.filter(date_modified__range=(today_min, today_max)).order_by('-date_modified') 

# get the rest of the data 
data_set2 = DataCollection.objects.all().exclude(date_modified__range=(today_min, today_max)).order_by('-date_created') 

# join it all together 
all_list = list(chain(data_set1, data_set2)) 

Я думаю, Джанго планировал ввести селектор __date запроса я не знаю, если это доступно, но пока что также может помочь

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