Django: упорядочение по последнему элементу в обратном отношении внешнего ключа

#python #django #django-queryset

#python #django #django-набор запросов

Вопрос:

Я пытаюсь реализовать qs.sort_by операцию, но я не уверен, как это сделать.

Учитывая следующие модели

 
class Group(models.Model):
    name = models.CharField(max_length=300)
    ( ... )


class Budget(models.Model):
    ( ... )
    amount = models.DecimalField(
        decimal_places=2,
        max_digits=8,
    )
    group = models.ForeignKey(
        Group,
        related_name="budgets",
        on_delete=models.CASCADE,
    )

  

Где для каждого Group 0 > 5 из них назначены бюджеты или

Я пытаюсь отсортировать Group.objects.all() набор запросов по их количеству last (например, по самому последнему назначению) Budget .

Я знаю, что если бы это было OneToOne , я мог бы сделать что-то вроде следующего:

 Group.objects.all().order_by('budget__amount')
  

С ForeignKey отношениями я надеялся, что смогу сделать что-то вроде

 Group.objects.all().order_by('budgets__last__amount')
  

Но, увы, это недопустимая операция, но я не уверен, как поступить иначе.

Кто-нибудь знает, как выполнить эту операцию сортировки? (если это действительно возможно)

Комментарии:

1. Вам придется использовать аннотацию , но у меня сейчас нет времени, чтобы просто ввести точный ответ для вас. Что-то вроде Group.objects.annotate(last_amount=Min('budget__amount').order_by('last_amount') .

2. Что определяет, что является последним? Есть ли у вас поле метки времени в бюджете?

3. На данный момент я использую значение первичного ключа по умолчанию. Все запросы используют логику Group.budget.last()

4. @Jasper У вас есть способ вручную получить каждый budgets__last__amount из них?

Ответ №1:

Это должно сделать это:

 latest = Budget.objects.filter(group=OuterRef('pk')).order_by('-pk')

Group.objects.annotate(
    latest_budget=Subquery(
        latest.values('amount')[:1]
    )
).order_by('latest_budget')
  

Ответ №2:

Вы можете попробовать использовать sorted с пользовательским ключом:

 sorted(Group.objects.all(), key=lambda x: x.last__budget__amount)
  

Возможно .last__budget__amount , это недопустимый метод, но вы поняли идею.

Комментарии:

1. Спасибо за ваш ответ! Увы, это приводит к object has no attribute 'last__budget__amount' . Использование last__ , похоже, не является допустимым методом в этом контексте.

2. @Jasper я знаю. Каким бы ни был ручной метод получения каждой последней суммы бюджета, вы можете применить это к x .

3. Не делайте в python того, что вы можете сделать в базе данных.