Запрос агрегации Django для связанных объектов "один ко многим"
Вот моя упрощенная модель:
class Item(models.Model):
pass
class TrackingPoint(models.Model):
item = models.ForeignKey(Item)
created = models.DateField()
data = models.IntegerField()
class Meta:
unique_together = ('item', 'created')
Во многих частях моего приложения мне нужно получить набор Item
и аннотировать каждый элемент data
поле из последних TrackingPoint
с каждого товара, заказанного created
поле. Например, экземпляр i1
класса Item
имеет 3 TrackingPoint
"S:
tp1 = TrackingPoint(item=i1, created=date(2010,5,15), data=23)
tp2 = TrackingPoint(item=i1, created=date(2010,5,14), data=21)
tp3 = TrackingPoint(item=i1, created=date(2010,5,12), data=120)
Мне нужен запрос для получения i1
экземпляр аннотирован tp1.data
значение поля как tp1
это последняя точка отслеживания, заказанная created
поле. Этот запрос также должен вернуть Item
это что не имеют TrackingPoint
это вообще. Если возможно, я предпочитаю не использовать QuerySet
"s extra
способ сделать это.
Это то, что я пытался до сих пор... и не удалось:(
Item.objects.annotate(max_created=Max('trackingpoint__created'),
data=Avg('trackingpoint__data')).filter(trackingpoint__created=F('max_created'))
Есть идеи?
2 ответа
Вот один запрос, который предоставит (TrackingPoint, Item)-пары:
TrackingPoint.objects.annotate(max=Max('item__trackingpoint__created')).filter(max=F('created')).select_related('item').order_by('created')
Вам придется запрашивать элементы без точек отслеживания отдельно.
Это не является прямым ответом на ваш вопрос, но в случае, если вам не нужно именно то, что вы описали, вас может заинтересовать решение "наибольшие числа групп". Вы можете посмотреть мой ответ на аналогичный вопрос:
Запрос Django, который получает самые последние объекты из разных категорий
- это должно относиться непосредственно к вашему делу:
items = Item.objects.annotate(tracking_point_created=Max('trackingpoint__created'))
trackingpoints = TrackingPoint.objects.filter(created__in=[b.tracking_point_created for b in items])
Обратите внимание, что вторая строка может дать неоднозначные результаты, если created
даты повторяются в модели TrackingPoint.