Как получить последние (отличные) записи, отфильтрованные по неуникальному полю в 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 пуст.

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