Как получить последние (отличные) записи, отфильтрованные по неуникальному полю в Django
Я продемонстрирую на примере. Вот модель (первичный ключ неявный):
class Item(models.Model):
sku = models.CharField(null=False)
description = models.CharField(null=True)
У меня есть список skus, мне нужно получить последние описания, которые записаны в таблице для модели Item. Latest item == greatest id.
Мне нужен способ аннотировать последнее описание:
Item.objects.values("sku").filter(sku__in=list_of_skus).annotate(latest_descr=Latest('description').order_by("-id")
но это не будет работать по разным причинам (исключая отсутствие агрегатной функции).
Item.objects.values("sku").filter(sku__in=list_of_skus).annotate(latest_descr=Latest('description').lastest("-id")
Или используйте это
Item.objects.values("sku").filter(sku__in=list_of_skus).annotate(latest_descr=Latest('description').order_by("-id").reverse()[0]
Я использовал функцию агрегации postgres ArrayAgg для агрегации последнего описания следующим образом:
from django.contrib.postgres.aggregates import ArrayAgg
class ArrayAggLatest(ArrayAgg):
template = "(%(function)s(%(expressions)s ORDER BY id DESC))[1]"
Item.objects.filter(sku__in=skus).values("sku").annotate(descr=ArrayAggLatest("description"))
Функция aggregate объединяет все описания, упорядоченные по убыванию ID исходной таблицы, и получает 1-й элемент (0-й элемент - None)
Ответ от @M.J.GH.PY или @dekomote war не верен. Если у вас есть модель:
class Item(models.Model):
sku = models.CharField(null=False)
description = models.CharField(null=True)
эта модель уже имеет по умолчанию order_by= 'id',
Вам не обязательно аннотировать что-то. Вы можете:
получить последний объект:
Item.objects.filter(sku__in=list_of_skus).last()
получить последнее значение description
:
Item.objects.filter(sku__in=list_of_skus).values_list('description', flat=True).last()
Оба варианта дают вам None
, если queryset
пуст.