下面是我的统计信息页面的views.py。此页面包含基于我的模型对象的大量计算。效果很好。但是,当我将django-filter应用于数据时,它不会更改。仅针对“空头”交易或“过去7天”的过滤示例。
我知道get_context_data基本上是对结果进行硬编码,并且不会受到任何过滤器查询的影响。这不是方法,但是我尝试了几项没有结果的事情,所以回到正题……我该怎么做?
我尝试过kwargs.update
和context.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
如您所指出的,第一个问题是您正在get_context_data()
中对结果进行硬编码。FilterView
ClassBasedView继承自Django的MultipleObjectsMixin mixin,因此您应该将两者都考虑在内。根据您的问题,我认为您没有在模板中使用object_list
属性-这是CBV填充数据的地方。
基本上,在当前视图中,流程将为:
get_queryset()
方法获取查询集。 queryset
属性model
。 Trade.objects.all()
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,因为它将在数据库级别进行所有这些计算。如果您开始处理大量数据,那么进行所有手动处理将是一个问题。
我认为这些要点将是一个好的开始!