django filter queryset show variables on template [duplicate]

允我心安 提交于 2020-06-08 14:20:25

问题


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".

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?

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

回答1:


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 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:

  • 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')
    
  • 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!



来源:https://stackoverflow.com/questions/61973937/django-filter-queryset-show-variables-on-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!