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")
Вы можете аннотировать User
s с last_purchase_pk
s, а затем получить эти данные и добавить их этим пользователям:
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
в случае отсутствия такой покупки.