代码之家  ›  专栏  ›  技术社区  ›  Florent

如何根据方法返回的值筛选Django对象?

  •  1
  • Florent  · 技术社区  · 4 年前

    我有一个Django对象和一个方法 get_volume_sum(self)

    例如,我可以这样做一个循环,但我想要一个更优雅的解决方案。

    vol = []
    obj = []
    for m in Market.object.filter(**args): #  3000 objects
        sum = m.get_volume_sum()
        vol.append(sum)
        obj.append(m.id)
    top = search_top_n(obj, vol, n)
    

    这就是这个方法的样子:

    # return sum of volume over last hours
    def get_volume_sum(self, hours):
        return Candle.objects.filter(market=self,
                                     dt__gte=timezone.now()-timedelta(hours=hours)
                                     ).aggregate(models.Sum('vo'))
    

    据我所见 here

    1 回复  |  直到 4 年前
        1
  •  1
  •   willeM_ Van Onsem    4 年前

    您不应使用该方法进行筛选,这将导致 N+1 问题:3000英镑 Market

    你可以在家里做这件事 大部分 .annotate(…) [Django-doc] :

    from django.db.models import Sum
    
    hours = 12  # some value for hours
    
    Market.objects.filter(
        **args,
        candle__dt__gte=timezone.now()-timedelta(hours=hours),
    ).annotate(
        candle_vol=Sum('candle__vo')
    ).order_by('-candle_vol')

    Candle 那么这些 集市 将过滤掉这些数据。我们也可以通过允许 蜡烛

    from django.db.models import Q, Sum
    
    hours = 12  # some value for hours
    
    Market.objects.filter(
        Q(candle__dt__gte=timezone.now()-timedelta(hours=hours)) |
        Q(candle=None),
        **args
    ).annotate(
        candle_vol=Sum('candle__vo')
    ).order_by('-candle_vol')