返回缺失值列表?

时间:2015-12-16 13:17:31

标签: python django django-rest-framework

以下行生成现有数据点列表:

datapoint_list = organisation.datapoint_set.filter(timestamp__gte=startDate, timestamp__lte=endDate)

我希望以JSON格式return startDatelastDate之间没有现有数据点的日期。

如何做到这一点?

我最好的想法是:

class Missing(generics.ListAPIView)
    ...
    queryset = organisation.datapoint_set.filter(timestamp__gte=startDate, timestamp__lte=endDate)

    Loop over the datesdelta
        Loop over the datapoints
            If datapoint.timestamp == datedelta.timestamp then
                Push timestamp to object
                Continue
            End if
        End loop
    End loop
    Return object

但我没有成功循环日期。也许甚至有一种更简单的方法可以做到这一点?

修改

datedelta是根据查询参数确定的,默认情况下应该查找上周缺少的数据点:

    days = int(self.request.query_params.get('days', 7))
    startDate = datetime.today() - timedelta(days)
    endDate = datetime.today()

查询集包含:

<DataPoint: Value: 123, Timestamp: 2015-12-15>
<DataPoint: Value: 123, Timestamp: 2015-12-11>
<DataPoint: Value: 123, Timestamp: 2015-12-10>
<DataPoint: Value: 123, Timestamp: 2015-12-09>
<DataPoint: Value: 123, Timestamp: 2015-12-08>

JSON输出应该类似于

[
    'date': '2015-12-16',
    'date': '2015-12-14',
    'date': '2015-12-13',
    'date': '2015-12-12',
    'date': '2015-11-07'
}

我的问题是如何从该查询集获取到该输出。

3 个答案:

答案 0 :(得分:2)

您可以使用values_list()从查询中获取所有时间戳。要仅获得结果中的不同值,您可以将values_listdistinct()

结合使用
timestamps = organisation.datapoint_set.filter(timestamp__gte=today-timedelta(days), timestamp__lte=today).values_list('timestamp',flat=True)

所以现在timestamps列表包含有一些数据点的所有时间戳。您可能希望首先将它们转换为字符串对象。

ts = [str(t) for t in timestamps]

现在循环从todaytoday-days

的日子
ts_list = []
for day in xrange(days+1):
    dat = datetime.today() + timedelta(days=-day)
    if str(dat) not in ts:
        print dat
        ts_list.append(dat)

这将给出所有没有数据点的日期

答案 1 :(得分:2)

set()学会使用它,你将统治世界!首先,对您的查询稍作修改,基于您向您显示的示例,只需要日期,这样可以提高查询效率:

queryset = organisation.datapoint_set.filter(timestamp__gte=startDate, timestamp__lte=endDate).values_list('timestamp', flat=True)

完成后,看起来像这样:

queryset = [datetime(2015,12,15), datetime(2015,12,11), datetime(2015,12,10), datetime(2015,12,9), datetime(2015,12,8)]

现在我们生成我们想要的值:

>>> set([endDate - timedelta(x) for x in xrange(days)])
set([datetime.date(2015, 12, 14), datetime.date(2015, 12, 16), datetime.date(2015, 12, 15), datetime.date(2015, 12, 12), datetime.date(2015, 12, 13), datetime.date(2015, 12, 10), datetime.date(2015, 12, 11)])

完美,我们(减去它们)-

>>> set([endDate - timedelta(x) for x in xrange(days)]) - set(queryset)
set([datetime.date(2015, 12, 14), datetime.date(2015, 12, 16), datetime.date(2015, 12, 15), datetime.date(2015, 12, 12), datetime.date(2015, 12, 13), datetime.date(2015, 12, 10), datetime.date(2015, 12, 11)])

让我们都很漂亮:

import datetime
days = 10
# a bit of a hack to get the current date without any time stuff.
endDate = datetime.datetime.combine(datetime.date.today(), datetime.datetime.min.time())
queryset = [datetime.datetime(2015,12,15), datetime.datetime(2015,12,11), datetime.datetime(2015,12,10), datetime.datetime(2015,12,9), datetime.datetime(2015,12,8)]
date_ranges = set([endDate - datetime.timedelta(x) for x in xrange(days)])
output = sorted(list(date_ranges - set(queryset)))
print([x.strftime('%Y-%m-%d') for x in output])

输出是:

['2015-12-07', '2015-12-12', '2015-12-13', '2015-12-14', '2015-12-16']

如果您的时间戳以date对象变得更加容易:

import datetime
days = 10
endDate = datetime.date.today()
queryset = [datetime.date(2015,12,15), datetime.date(2015,12,11), datetime.date(2015,12,10), datetime.date(2015,12,9), datetime.date(2015,12,8)]
date_ranges = set([endDate - datetime.timedelta(x) for x in xrange(days)])
output = sorted(list(date_ranges - set(queryset)))
print([x.strftime('%Y-%m-%d') for x in output])

答案 2 :(得分:1)

你可以这样做:

class MissingListApiView(generics.ListAPIView)
    model = Organisation
    serializer_class = OrganisationSerializer

    def get_queryset(self):

       datapoint_list = organisation.datapoint_set.filter(timestamp__gte=today-timedelta(days), timestamp__lte=today)
       get_timestap = lambda x: x.timestamp
       timestamp_list = map(get_timestap, datapoint_list)
       response = list()
       push = response.append
       for day in xrange(days+1):
          date = datetime.today() + timedelta(days=-day)
          if str(dat) not in timestamp_list:
             push(datapoint.timestamp)
       Return response