Django Получение последнего объекта для каждого значения в списке

У меня есть модель Purchase, с двумя полями, User и amount_spent.

Это models.py:

class Purchase(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    amount_spent = models.IntegerField()
    created_at = models.DateTimeField(auto_now_add=True)

Я хочу получить последние покупки из списка пользователей. На views.py у меня есть список с некоторыми объектами User, и я хочу получить последнюю покупку для каждого пользователя в списке. Я не могу найти способ сделать это в одном запросе, я проверил оператор latest() на QuerySets, но он возвращает только один объект.

Это views.py:

purchases = Purchase.objects.filter(user__in=list_of_users)
# purchases contains all the purchases from users, now I need to get the most recent onces for each user.

Сейчас я могу сгруппировать purchases по пользователям и получить самые последние, но мне интересно, есть ли способ сделать это одним запросом к DB.

попробуйте это:

Purchase.objects.filter(user__in=list_of_users).values("user_id", "amount_spent").order_by("-id").distinct("user_id")

Вы можете аннотировать Users с last_purchase_pks, а затем получить эти данные и добавить их этим пользователям:

from django.db.models import OuterRef, Subquery

users = User.objects.annotate(
    last_purchase_pk=Subquery(purchase.objects.order_by('-created_at').filter(user_id=OuterRef('pk')).values('pk')[:1])
)

purchases = {
    p.pk: p
    for p in Purchase.objects.filter(
        pk__in=[user.last_purchase_pk for user in users]
    )
for user in users:
    user.last_purchase = purchases.get(user.last_purchase_pk)

После этого фрагмента кода, объекты User в users будут иметь атрибут last_purchase, который содержит последнюю Purchase для этого пользователя, или None в случае отсутствия такой покупки.

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