Django过滤器queryset在模板上显示变量 [英] django filter queryset show variables on template

查看:94
本文介绍了Django过滤器queryset在模板上显示变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Below is the views.py to my stats page. This page has a bunch of calculations based on my model objects. Works great. However when I apply django-filter to the data it does not change. Example filtering for only "short" trades or in the "last 7 days".

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

I know that get_context_data is basically hardcoding the results and it will not be affected by any filter query. This is not the approach but I've tried several things with no results so back to square one... How would I do this?

我已经尝试了 kwargs.update context.update ,但也没有得到结果。

I've tried kwargs.update and context.update but also was not getting results.

这看起来应该是非常明显的,因为人们还会显示和过滤对象的统计信息吗?

This seems like it should be super obvious as how else do people show and filter statistics on objects?

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


推荐答案

第一个问题,就像你指出的那样,是你很难在 get_context_data()中对结果进行编码。 FilterView ClassBasedView继承自 MultipleObjectsMixin 混合,因此您应该将两者都考虑在内。根据您的问题,我认为您没有在模板中使用 object_list 属性-这是CBV填充数据的地方。

The first problem, like you pointed, is that you are hard-coding the results in the get_context_data(). The FilterView ClassBasedView inherits from the MultipleObjectsMixin mixin of Django, so you should take both into account. I assume from your issues that you are not using the object_list property in your template - that's where the CBV populates the data.

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

Basically, in your current view, the flow will go as:


  • 根据 get_queryset()方法获取查询集。

  • 如果不存在,它将使用定义的 queryset 属性

  • 最后一种情况是模型。 <-这是您的情况,因此它将使用 Trade.objects.all()

  • 将FilterSet应用于原始查询集

  • 分页(如果已配置),然后在上下文中将过滤后的查询集分配给 object_list

  • get the queryset based in the get_queryset() method.
  • If this doesn't exist, it will use the queryset property defined
  • In last case, the model. <-- This is your case, so it will use Trade.objects.all()
  • the FilterSet is applied to the original queryset
  • paginate (if you have it configured) and assign the filtered queryset to the object_list in the context.

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

So, some changes you can start trying:


  • 使用 object_list get_context_data()中执行统计计算,而不是查询自己进行交易建模。

  • 如果始终要根据当前用户过滤结果,则可以使用 get_queryset()方法从那里应用该过滤器,所以您可以这样做:

  • Use the object_list to perform the stats calculation in your get_context_data() instead of querying for the Trade model yourself.
  • If you are always going to filter the results based in the current user, you can use the get_queryset() method to apply that filter from there, so you would do:

def get_queryset(self):
    qs = super().get_queryset()
    return qs.filter(user=self.request.user, status='cl')


  • 我还建议您查看Django内置的数据聚合机制,因为它将在数据库级别进行所有这些计算。如果您开始处理大量数据,那么进行所有手动处理将是一个问题。

  • I would also recommend you to look at Django's built-in data aggregation mechanisms, as it would make all those calculations at DB level. If your start to treat big amounts of data, making all this manual processing is going to be an issue.

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

    I think those points would be a good start!

    这篇关于Django过滤器queryset在模板上显示变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆