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

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

问题描述

下面是我的统计页面的 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.updatecontext.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 是 Django 的 mixin,所以你应该把两者都考虑在内.我从您的问题中假设您没有在模板中使用 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属性
  • 在最后一种情况下,model.<-- 这是您的情况,因此它将使用 Trade.objects.all()
  • 过滤器集应用于原始查询集
  • 分页(如果已配置)并将过滤后的查询集分配给上下文中的 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() 中执行统计计算,而不是自己查询 Trade 模型.
  • 如果您总是要根据当前用户过滤结果,您可以使用 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 think those points would be a good start!

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

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