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

在Django中,我如何构建查询集,以便在时间片上按时间进行过滤?

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

    我使用的是Python 3.9和Django 3.2。我有这个价格模型

    class Price(models.Model):
        id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
        price = models.FloatField(null=False)
        created = models.DateTimeField(null=False, default=datetime.now)
    

    如果我想得到过去24小时内每小时的价格,我可以运行这样的方法

    def _get_prices_per_time_slice(self, last_hours=24):
        now = timezone.now()
        end_time = now.replace(second = 0, microsecond = 0)
        start_time = end_time - timedelta(hours=last_hours)
        qset = Price.objects.filter(
            created__range=[start_time, end_time],
            created__minute=end_time.minute
        ).values('price')
        return [r['price'] for r in qset]
    

    但假设我想每X个小时得到一次价格。

    def _get_prices_per_time_slice(self, last_hours=24, time_slice_in_hours=4):
    

    因此,如果当前时间是午夜(零秒零分),我想获得午夜、晚上8点、下午4点、中午、上午8点和凌晨4点的价格。如何添加过滤器以每X小时筛选一次价格?

    0 回复  |  直到 4 年前
        1
  •  -1
  •   Archana David    4 年前

    python中的range函数有助于指定增量步长值

    语法: range(start, stop, step)

    
    x = range(3, 20, 4)
    
    for n in x:
      print(n)
    #Gives output 
    >>> 3
    >>> 7
    >>> 11
    >>> 15
    >>> 19
    
    

    只需重写 created_range 添加步长值 time_slice_in_hours

       created__range=[start_time, end_time, time_slice_in_hours] 
    

    选项1

    
    def _get_prices_per_time_slice(self, last_hours= 24,time_slice_in_hours=4):
        now = timezone.now()
        end_time = now.replace(second = 0, microsecond = 0)
        start_time = end_time - timedelta(hours=last_hours)
        qset = Price.objects.filter(
            created__range=[start_time, end_time, time_slice_in_hours],
            created__minute=end_time.minute
        ).values('price')
        return [r['price'] for r in qset]
    
    

    但是中的语法 django query set api official documentation 未能在中提及步骤参数 __range() 函数,即它可能不受支持 created__range .

    选项2

    在这种情况下,您可以使用以下函数来计算时间范围 x_time_slice_list 使用Python DateTimeRange 作用 official documentation )并评估为 created__in

    
    from datetimerange import DateTimeRange
    from dateutil.relativedelta import relativedelta
    
    def _get_prices_per_time_slice(self, last_hours= 24,time_slice_in_hours=4):
        now = timezone.now()
        end_time = now.replace(second = 0, microsecond = 0)
        start_time = end_time - timedelta(hours=last_hours)
        x_time_slice_list= []
    
        time_range = DateTimeRange(start_time, end_time)
        for value in time_range.range(relativedelta(hours=+time_slice_in_hours)):
               x_time_slice_list.append(value)
    
        qset = Price.objects.filter(
            created__in= x_time_slice_list,
            created__minute=end_time.minute
        ).values('price')
        return [r['price'] for r in qset]
    
    
        2
  •  -1
  •   Chad Lamb    4 年前

    您可以通过在python中处理时间片过滤来实现这一点。

    我的意思是,如果你接受你的函数。即

    def _get_prices_per_time_slice(self, last_hours=24):
        now = timezone.now()
        end_time = now.replace(second = 0, microsecond = 0)
        start_time = end_time - timedelta(hours=last_hours)
        qset = Price.objects.filter(
            created__range=[start_time, end_time],
            created__minute=end_time.minute
        ).values('price')
        return [r['price'] for r in qset]
    
    

    并按照如下方式重写它,以返回创建的数据并处理返回列表理解中的过滤。

    def _get_prices_per_time_slice(self, last_hours=24, time_slice_in_hours=4):
        now = timezone.now()
        end_time = now.replace(second = 0, microsecond = 0)
        start_time = end_time - timedelta(hours=last_hours)
        qset = Price.objects.filter(
            created__range=[start_time, end_time],
            created__minute=end_time.minute
        ).values('price', 'created')
        return [r.get('price') for r in qset if r.get('created').hour % time_slice_in_hours == 0]
    
    
    推荐文章