Следующая строка выводит список существующих точек данных:
datapoint_list = organisation.datapoint_set.filter(timestamp__gte=startDate, timestamp__lte=endDate)
Я хотел бы return
в формате JSON датами от startDate
до lastDate
, для которых нет существующей точки данных.
Как это может быть сделано?
Моя лучшая идея состоит в том, чтобы:
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 ответа
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])
Вы можете сделать следующее:
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
Вы можете получить все временные метки из запроса, используя values_list () а> . Чтобы получить только отдельные значения в результате, вы можете объединить values_list
с Different ()
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]
Теперь переберите дни с today
до today-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)
Это даст все даты, которые не имеют точек данных
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.