Django получить СУММУ результата функции от всех объектов - PullRequest
0 голосов
/ 11 марта 2020

Что-то подсказывает мне, что этот вопрос будет очень очевидным, но я застрял на нем, поскольку весь поиск, который я провел, в основном заканчивается вычислением суммы всех объектов, что и делает контекст ['all_trades']. Однако я рассчитываю вычислить сумму всех результатов объекта, вычисленных в функции. Я надеюсь, что это правильно сформулировано.

Если я распечатаю контекст, это будет результат:

{'view': <portfolios.views.StatsView object at 0x0000020CC8B0D188>, 'all_trades': 13, 'gross_profit': <function Trade.get_profit_loss_value at 0x0000020CC70598B8>}

models.py

class Trade(models.Model):
    class Meta:
        verbose_name = "Trade"
        verbose_name_plural = "Trades"

    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
    ...

    # P/L Value = Sum of all buys * ( Entry Cost Per Unit (CPU) - Exit Cost Per Unit (CPU) )
    def get_profit_loss_value_or_None(self):
        if self.get_exit_cpu() > 0:
            if self.type == 'Long':
                result = self.get_entries().aggregate(
                get_profit_loss_value=Sum('amount', output_field=models.FloatField()
                                           ) * (self.get_exit_cpu() - self.get_entry_cpu()))['get_profit_loss_value']
            return 0 if result is None else result
        elif self.type == 'Short':
            result = self.get_entries().aggregate(
            get_profit_loss_value=Sum('amount', output_field=models.FloatField()
                                           ) * -1 * (self.get_exit_cpu() - self.get_entry_cpu()))['get_profit_loss_value']
            return 0 if result is None else result
        else:
            return 0

    def get_profit_loss_value(self):
        ret = self.get_profit_loss_value_or_None()
        return 0 if ret is None else ret

views.py

class StatsView(TemplateView):
    template_name = 'dashboard/stats.html'

    def get_context_data(self, *args, **kwargs):
        context = super(StatsView, self).get_context_data(*args, **kwargs)
        # get # of trades user made
        context['all_trades'] = Trade.objects.filter(user=self.request.user).count()
        # get sum of all trades profit/loss
        context['gross_profit'] = Trade.get_profit_loss_value 
        return context

Основываясь на ответе Дина Эллиотта, сделанные до сих пор корректировки в views.py

class StatsView(TemplateView):
    template_name = 'dashboard/stats.html'

    def get_context_data(self, *args, **kwargs):
        trade = Trade.objects.filter(user=self.request.user)
        context = super(StatsView, self).get_context_data(*args, **kwargs)
        context['all_trades'] = Trade.objects.filter(user=self.request.user).count()
        context['gross_profit'] = trade.get_profit_loss_value()
        #context['net_profit'] = Trade.objects.filter(user=self.request.user).count()
        print(context['gross_profit'])
        return context

приводит к ошибке:

line 352, in get_context_data
    context['gross_profit'] = trade.get_profit_loss_value()
AttributeError: 'QuerySet' object has no attribute 'get_profit_loss_value'

Ответы [ 2 ]

1 голос
/ 11 марта 2020

Вы должны использовать метод get() вместо filter() при получении trade в get_context_data() методе, как показано ниже ...

def get_context_data(self, *args, **kwargs):
    trade = Trade.objects.get(user=self.request.user)

вместо ...

def get_context_data(self, *args, **kwargs):
    trade = Trade.objects.filter(user=self.request.user)

ИЛИ

Если вы хотите использовать filter(), тогда используйте first() для получения одного объекта из него, как показано ниже ...

def get_context_data(self, *args, **kwargs):
    trade = Trade.objects.filter(user=self.request.user)
    ... YOUR LOGIC ...
    profit_loss = sum([t.get_profit_loss_value() for t in trade])
    context['gross_profit'] = profit_loss
    ... YOUR LOGIC ...        

Итак, это даст вам первый элемент из queryset.

0 голосов
/ 11 марта 2020

Похоже, вам нужен Trade объект для context['gross_profit'] = Trade.get_profit_loss_value. Например, trade = Trade.objects.get(id=1), а затем используйте trade.get_profit_loss_value().

Обязательно добавьте скобки! Без скобок вы только ссылаетесь на функцию, но не вызываете ее.

...