Как упорядочить набор queryset, сохраняя объекты, сгруппированные по другому полю?

У меня есть модель с двумя полями дата и тип class Obj(Model): date = DateTimeField type = ChoiceField Я хочу упорядочить их по дате создания, но хочу, чтобы объекты одного типа держались вместе ОБЪЕКТ:

    <<<1><1>>01.01.2022 СИНИЙ
  • 02.01.2022 ЧЕРНЫЙ
  • 03.01.2022 СИНИЙ
  • 04.01.2022 ЗЕЛЕНЫЙ
  • 05.01.2022 СИНИЙ
  • 06.01.2022 BLACK
  • 07.01.2022 GREEN
  • Когда я делаю заказ, я хочу, чтобы он сначала посмотрел на дату, получил последнюю дату, затем взял все объекты с типом этого объекта и расположил их в порядке, сохраняя порядок дат среди них, а затем взял следующую дату второго типа и расположил их в порядке после предыдущего:

    УПОРЯДОЧЕН:

    • 07.01.2022 ЗЕЛЕНЫЙ
    • 04.01.2022 ЗЕЛЕНЫЙ
    • 06.01.2022 ЧЕРНЫЙ
    • 02.01.2022 ЧЕРНЫЙ
    • 05.01.2022 СИНИЙ
    • 03.01.2022 BLUE
    • 01.01.2022 BLUE

    По сути, я хочу сначала упорядочить_по_заголовку, а затем упорядочить группы по дате. Могу ли я сделать это тривиально или мне придется использовать Case When или, возможно, даже необработанный SQL. Было бы лучше, если бы я мог избежать необработанного SQL, потому что это постранично

    Правильно, я думаю, что у меня есть ответ для вас, который работает - вам нужно использовать Subquery и OuterRef. Первый набор запросов упорядочивает все модели Obj по нужной вам дате, но фильтруется с помощью OuterRef - OuterRef получает поле type из второй строки.

    Вторая строка затем выполняет аннотацию с подзапросом первой строки, .values('date')[:1] получает последнее значение даты (которое вы можете захотеть изменить). Аннотация означает, что каждый объект помечен датой, когда был создан самый новый объект этого типа.

    from django.db.models import OuterRef, Subquery
    
    dates = Obj.objects.filter(type=OuterRef('type')).order_by('-date')
    Obj.objects.annotate(
        newest_creation=Subquery(dates.values('date')[:1])
    ).order_by('date', 'newest_creation')
    

    Возможно, вам придется изменить порядок следования даты и newest_creation, чтобы получить желаемый порядок.

    Вернуться на верх