【问题标题】:django filter queryset show variables on template [duplicate]django过滤器查询集在模板上显示变量[重复]
【发布时间】:2020-09-10 09:51:27
【问题描述】:

下面是我的统计页面的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】:

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

    基本上,在您当前的视图中,流程将如下所示:

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

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

    • 使用object_list 在您的get_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,因为它会在数据库级别进行所有这些计算。如果您开始处理大量数据,那么进行所有这些手动处理将是一个问题。

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

    【讨论】:

    • 嘿@jjoseba 感谢您的回答尝试。一直在尝试根据您的反馈找到解决方案,但仍然没有结果。奇怪的是,这太棘手了,因为想要查询设置 get_context 似乎是一种非常常见的情况。也许我错了。我想我将通过将统计信息移入模式来开始链接到解决方案。
    • 没有看到全貌很难进一步帮助你......我建议你仔细阅读基于类的视图文档和django-filter 文档并从一个小例子开始:只是一个列表视图使用基于一个字段进行过滤的模型。一旦你得到这个工作,尝试将它扩展到你的实际问题。祝你好运!
    猜你喜欢
    • 2023-04-11
    • 1970-01-01
    • 2018-09-02
    • 2020-10-17
    • 2022-01-12
    • 2023-03-07
    • 2021-04-21
    • 2012-05-15
    • 2019-07-29
    相关资源
    最近更新 更多