2015-02-26 3 views
0

Вот мой Django модель:Почему django.db.models.Avg() возвращает объект datetime? И почему это неправильно?

class MyModel(models.Model): 
    a = IntegerField() 
    b = DateTimeField() 

Вот QuerySet я исполняю на этой модели, чтобы найти количество, мин, макс и среднее b сек для каждого значения a:

>>> MyModel.objects.values('a').annotate(count=Count("b"), min=Min('b'), max=Max('b'), avg=Avg('b')) 

{'a': 1, 'count': 2, 
'avg': 20150226046183.0, 
'min': datetime.datetime(2015, 2, 26, 1, 8, 22, tzinfo=<UTC>), 
'max': datetime.datetime(2015, 2, 26, 8, 15, 44, tzinfo=<UTC>)} 

Look при значении, связанном с ключом avg. Это поплавок. Зачем? Среднее значение DateTimeFields должно быть DateTimeField, не так ли? Так почему же это поплавок? Я даже мог понять строку, но определенно не поплавок. Это не десятичные числовые данные.

Как только мы преодолеем эту проблему, я смогу проанализировать данные из поплавка, чтобы выяснить, что означает Django. Я вижу, что 20150225, очевидно, означает 26 февраля 2015 года. Но подождите, это означает, что время суток будет представлено 046183.0. Что это значит? 4:61 утра и 83 секунды ?? Это не имеет никакого смысла.

Может кто-нибудь, пожалуйста, объясните мне все это? Кажется, что это беспорядок.

+0

В среднем, 2 марта 2014 года, 3 сентября 1886 года и 12 декабря 1949 года? –

+0

@LegoStormtroopr Я думал так: каждое datetime может быть представлено как точка на полуоткрытом сегменте линии с определенной конечной точкой (поэтому его можно представить как числовое значение, например, как время, прошедшее с конечной точки, поэтому среднее арифметическое вычислимая). – krneki

ответ

1

От django's source code, он всегда возвращается float. Похоже, что намерение Avg должно использоваться с числами.

Вы можете попробовать конвертировать возвращенный float с помощью strptime, я не пробовал это, и я уверен, что если число с поплавком вернется, это среднее значение, которое вы ищете.

2

Из исходного кода Avg всегда возвращает число с плавающей точкой:

class Avg(Aggregate): 
    function = 'AVG' 
    name = 'Avg' 

    def __init__(self, expression, **extra): 
     super(Avg, self).__init__(expression, output_field=FloatField(), **extra) 

    def convert_value(self, value, expression, connection, context): 
     if value is None: 
      return value 
     return float(value) 

Что вы могли бы сделать, это превратить ваш объект DATETIME в Отметка времени Unix (число секунд, прошедших с начала 1970 года без високосных секунд) и вычислить среднее значение с помощью метода extra().

MyModel.objects.extra('avg': 'AVG(UNIX_TIMESTAMP(b))'.values('avg') 

Я предлагаю вам прочитать this до преобразования между временными и датой и временем объектами UNIX, так как вы должны принять во внимание разницы между наивными и осведомленными DateTimes.

+0

Ваш ответ полезен и приближает меня. Но это создает для меня другие проблемы. В ответе, который вы отправили, также есть некоторые синтаксические ошибки. Поэтому я задал аналогичный вопрос здесь: http://stackoverflow.com/questions/28758714/how-to-write-a-django-queryset-the-properly-computes-average-of-datetimefield-wi –