Как отсортировать по сумме связанных полей в Django, используя представления на основе классов? - PullRequest
3 голосов
/ 21 января 2020

Если у меня есть модель агента, которая выглядит следующим образом:

class Agent(models.Model):
    name = models.CharField(max_length=100)

и связанная модель, которая выглядит следующим образом:

class Deal(models.Model):
    agent = models.ForeignKey(Agent, on_delete=models.CASCADE)
    price = models.IntegerField()

и вид, который выглядит следующим образом :

from django.views.generic import ListView

class AgentListView(ListView):    
    model = Agent

Я знаю, что могу настроить порядок сортировки агентов в queryset, и я даже знаю, как отсортировать агентов по количеству заключенных ими сделок, так:

queryset = Agent.objects.all().annotate(uc_count=Count('deal')).order_by('-uc_count')

Однако я не могу понять, как отсортировать сделки по сумме цен сделок для каждого агента.

Ответы [ 2 ]

2 голосов
/ 21 января 2020

Учитывая, что вы уже знаете, как комментировать и сортировать эти аннотации, вы на 90% пути к этому. Вам просто нужно использовать агрегат Sum и следовать обратной связи.

Документы Django дают этот пример :

Author.objects.annotate(total_pages=Sum('book__pages'))

Вы должны быть в состоянии чтобы сделать что-то похожее:

queryset = Agent.objects.all().annotate(deal_total=Sum('deal__price')).order_by('-deal_total')

Мое чувство секретности подсказывает мне, что вам может понадобиться добавить distinct=True к агрегации Sum, но я не уверен без тестирования.

1 голос
/ 27 января 2020

Опираясь на ответ, который Грег Калека и на вопрос, который вы задали под его ответом, это, вероятно, решение, которое вы ищете:

from django.db.models import Case, IntegerField, When

queryset = Agent.objects.all().annotate(
    deal_total=Sum('deal__price'),
    o=Case(
        When(deal_total__isnull=True, then=0), 
        default=1, 
        output_field=IntegerField()
    )
).order_by('-o', '-deal_total')

Объяснение:

Что происходит, так это то, что поле deal_total складывает price объекта deal s, но если Agent не имеет deal s для начала, сумма price s None Объект When может присвоить deal_total значение 0, в противном случае ему было бы присвоено значение None

.
...