Django过滤器查询集在模板上显示变量

问题描述 投票:0回答:1

下面是我的统计信息页面的views.py。此页面包含基于我的模型对象的大量计算。效果很好。但是,当我将django-filter应用于数据时,它不会更改。仅针对“空头”交易或“过去7天”的过滤示例。

我知道get_context_data基本上是对结果进行硬编码,并且不会受到任何过滤器查询的影响。这不是方法,但是我尝试了几项没有结果的事情,所以回到正题……我该怎么做?

我尝试过kwargs.updatecontext.update,但也没有得到结果。

这似乎应该非常明显,因为人们还可以显示和过滤对象的统计信息吗?

views.py

class StatsView(LoginRequiredMixin, FilterView):
    model = Trade
    template_name = 'dashboard/stats.html'
    filterset_class = StatsFilter

    def get_form(self, *args, **kwargs):
        form = StatsFilter()
        user = self.request.user
        form.fields['associated_portfolios'].queryset = Portfolio.objects.filter(user=user)
        return form

    def get_max_consecutive_wins(self, data):
        longest = 0
        current = 0
        for num in data:
            if num > 0:
                current += 1
            else:
                longest = max(longest, current)
                current = 0

        return max(longest, current)

    def get_max_consecutive_loses(self, data):
        longest = 0
        current = 0
        for num in data:
            if num < 0:
                current += 1
            else:
                longest = max(longest, current)
                current = 0

        return max(longest, current)

    def get_context_data(self, *args, **kwargs):
        trade = Trade.objects.filter(user=self.request.user, status='cl').order_by('created')
        all_trades = Trade.objects.filter(user=self.request.user, status='cl').count()
        context = super(StatsView, self).get_context_data(*args, **kwargs)
        data = [t.profit_loss_value_fees for t in trade]

        win_trades_count = [t.trade_result for t in trade].count('win')
        loss_trades_count = [t.trade_result for t in trade].count('loss')
        scratch_trades_count = [t.trade_result for t in trade].count('scratch')

        avg_win = 0 if win_trades_count == 0 else mean(t.profit_loss_value_fees for t in trade if t.trade_result == 'win')
        avg_loss = 0 if loss_trades_count == 0 else mean(t.profit_loss_percent for t in trade if t.trade_result == 'win')
        avg_win_percent = 0 if win_trades_count == 0 else mean(t.profit_loss_percent for t in trade if t.trade_result == 'win')
        avg_loss_percent = 0 if loss_trades_count == 0 else mean(t.profit_loss_percent for t in trade if t.trade_result == 'loss')

        context['all_trades'] = all_trades
        context['gross_profit'] = sum([t.profit_loss_value for t in trade])
        context['net_profit'] = sum([t.profit_loss_value_fees for t in trade])
        context['win_trades_profit'] = sum(
                t.profit_loss_value_fees for t in trade if t.trade_result == 'win')
        context['loss_trades_profit'] = sum(
                t.profit_loss_value_fees for t in trade if t.trade_result == 'loss')
        context['win_trades_count'] = win_trades_count
        context['loss_trades_count'] = loss_trades_count
        context['scratch_trades_count'] = scratch_trades_count
        context['win_trades_count_ratio'] = win_trades_count / all_trades * 100
        context['loss_trades_count_ratio'] = loss_trades_count / all_trades * 100
        context['scratch_trades_count_ratio'] = scratch_trades_count / all_trades * 100
        context['total_fees'] = sum([t.get_fees() for t in trade])
        context['avg_win'] = avg_win
        context['avg_loss'] = avg_loss
        context['avg_win_percent'] = avg_win_percent
        context['avg_loss_percent'] = avg_loss_percent
        context['avg_position_size'] = mean(t.position_size for t in trade)
        context['largest_winning_trade'] = max([t.profit_loss_value_fees for t in trade])
        context['largest_losing_trade'] = min([t.profit_loss_value_fees for t in trade])
        context['largest_winning_trade_percent'] = max([t.profit_loss_percent for t in trade])
        context['largest_losing_trade_percent'] = min([t.profit_loss_percent for t in trade])
        context['max_consecutive_wins'] = self.get_max_consecutive_wins(data)
        context['max_consecutive_loses'] = self.get_max_consecutive_loses(data)
        context['qs'] = Trade.objects.filter(user=self.request.user, status='cl').order_by('created')

        return context
django django-models django-rest-framework django-views django-filter
1个回答
0
投票

如您所指出的,第一个问题是您正在get_context_data()中对结果进行硬编码。FilterViewClassBasedView继承自Django的MultipleObjectsMixin mixin,因此您应该将两者都考虑在内。根据您的问题,我认为您没有在模板中使用object_list属性-这是CBV填充数据的地方。

基本上,在当前视图中,流程将为:

  • 基于get_queryset()方法获取查询集。
  • 如果不存在,它将使用定义的queryset属性
  • 在最后一种情况下,为modelTrade.objects.all()
  • FilterSet应用于原始查询集
  • 分页(如果已配置它),然后在上下文中将过滤后的查询集分配给object_list

因此,您可以开始尝试一些更改:

  • 使用object_listget_context_data()中执行统计信息计算,而不是自己查询Trade模型。
  • 如果您总是要根据当前用户过滤结果,则可以使用get_queryset()方法从那里应用该过滤器,因此您可以这样做:

    def get_queryset(self):
        qs = super().get_queryset()
        return qs.filter(user=self.request.user, status='cl')
    
  • 我还建议您查看Django的内置data aggregation mechanisms,因为它将在数据库级别进行所有这些计算。如果您开始处理大量数据,那么进行所有手动处理将是一个问题。

我认为这些要点将是一个好的开始!

© www.soinside.com 2019 - 2024. All rights reserved.