Django / Python: Сортировка QuerySet по полю в первом экземпляре отношения foreignkey
У меня есть следующие 2 модели, модель Lesson, которая может иметь несколько дат начала / окончания - каждая со своей собственной моделью Date.
class Lesson(models.Model):
name = models.Charfield()
(...)
class Date(models.Model):
meeting = models.ForeignKey(
Lesson,
verbose_name="dates",
on_delete=models.CASCADE,
)
start_date = models.DateTimeField(
blank=True,
null=True,
)
end_date = models.DateTimeField(
blank=True,
null=True,
)
Для нашего проекта нам нужно упорядочить Lessons по start_date их самому раннему Date экземпляру.
Например, если у меня есть следующие данные:
MEETING A:
DATE_1a: 2022-11-01 --> 2022-11-02
DATE_2a: 2022-12-10 --> 2022-12-11
MEETING B:
DATE_1b: 2022-11-03 --> 2022-11-04
DATE_2b: 2022-11-05 --> 2022-11-06
Затем набор запросов должен вернуть [<MEETING A>, <MEETING B>] на основе start_date значений экземпляров DATE_1a/b. (2022-11-01 раньше, чем 2022-11-03, все остальные даты игнорируются)
Однако то, что, как я думал, будет относительно простым запросом, оказалось довольно коварной проблемой. Мой первоначальный подход метода по умолчанию order_by использовал все экземпляры Date, присоединенные к Meeting (и, что еще хуже, возвращал отдельный результат Meeting для каждого экземпляра Date)
qs.order_by(F("dates__start_date").asc(nulls_first=True))
Однако я не смог придумать запрос для выполнения того, что нам нужно. Мое текущее рабочее решение заключается в использовании целой кучи кода python, чтобы вместо этого сделать:
ordered_meetings = []
meeting_dict = {}
for meeting in qs:
first_date = meeting.dates.first()
if not meeting_dict.get(meeting.id):
meeting_dict[meeting.id] = first_date.start_date
А затем упорядочиваем dict на основе значений дат, используя ID/KEYS для получения Meeting экземпляров и добавления их в ordered_meetings список.
Но это настолько запутанный (и гораздо более медленный) подход, что я чувствую, что я, должно быть, что-то упускаю. Кто-нибудь знает более лаконичный метод достижения того, что мы хотим?
Полагаю, вам нужен мин?
Что-то вроде (не проверено):
Meeting.objects.annotate(first_date=Min('dates__start_date')).order_by('first_date')