Как агрегировать данные гистограммы для объемов регистраций в день от авторизации Django?

Модель пользователя Django auth имеет date_joined DateTimeField. Можно ли это использовать для агрегирования списка с объемами регистраций в день в течение дней (или других периодов времени) в диапазоне дат? Например: [(21.01, 5), (22.01, 7), (23.01, 9), ...] Как это сделать быстрее всего? Например. если диапазон дат на гистограмме был установлен на последние 3 года.

Я просмотрел http://docs.djangoproject.com/en/dev/topics/db/aggregation/, но непонятно, как разбивать объекты по временным меткам. Это распространенный шаблон проектирования в статистике.


person fmalina    schedule 20.01.2011    source источник


Ответы (2)


Этот вопрос похож на этот: django: совокупный запрос на основе временного диапазона

Что-то вроде этого должно работать: MyObject.objects.filter(date_joined__date__range=(weekago,today)).annotate(registrations=Count('id')

person Lyle Pratt    schedule 21.01.2011
comment
Не совсем, я получу дату и время from datetime import datetime, timedelta и модель пользователя from django.contrib.auth.models import User, теперь я выбираю последние 90 дней past90d = (datetime.now() - timedelta(days=30), datetime.now()) сейчас попробую ваш совет: signups = User.objects.filter(date_joined__date__range = past90d).annotate(registrations = Count('id')). Получается: присоединение к полю date_joined запрещено. Хорошо, я уберу date__range=, оставив только __range=. Без игральных костей, это возвращает список пользовательских объектов вместо ожидаемого списка дней с количеством регистраций. Любые идеи? - person fmalina; 31.01.2011

Вот мой код для создания гистограмм на основе дат с помощью Django и CSS.

def date_barchart(model, date_field, operation='count', days=150, till=datetime.now()):   
    list = []
    i = 0
    while i < days:
        day = (till - timedelta(days=i), till - timedelta(days=i-1))
        date = time.strftime("%Y-%m-%d", day[0].timetuple())
        kwargs = {'%s__range' % date_field: day}
        qs = model.objects.filter(**kwargs)
        if operation == 'count':
            total = qs.count()
        else:
            total = qs.aggregate(Sum('amount'))
            total = total['amount__sum']
        if total > 0:
            list.insert(0, {'date': date, 'total': total, 'round_total': int(total)})

        i = i + 1
    return list

На мой взгляд, я добавляю данные гистограммы в контекст шаблона:

'barchart': date_barchart(User, 'date_joined')

или для электронной коммерции Satchmo

'barchart': date_barchart(Payment, 'time_stamp', 'sum', 150)

шаблон:

{% if barchart %}
<div class="barchart">
    <ol>
        {% for d in barchart %}
        <li><u style="height:{{ d.round_total }}px"><i>{{ d.date }}<br>
            <b>{{ d.total }}</b></i></u></li>
        {% endfor %}
    </ol>
</div>
{% endif %}

и CSS:

.barchart{width:100%;overflow:hidden}
.barchart u{display:inline-block;position:relative;vertical-align:bottom;width:5px;background:#6cc;border-right:1px solid #fff;text-decoration:none}
.barchart u i{display:none;position:absolute;background:#fff;border:1px solid #aaa;padding:5px;border-radius:5px;left:-6px;bottom:10px;width:60px;font-size:10px;font-style:normal;color:#000}
.barchart u:hover{background-color:#333}
.barchart u:hover i{display:inline-block;z-index:500}
.barchart li{margin:0;padding:0;list-style:none;display:inline-block}

Выглядит так же хорошо, как Google Analytics, но мне не нужно раскрывать данные о моей эффективности.

person fmalina    schedule 02.02.2011
comment
Если у вас есть какие-либо идеи о том, как сделать это быстрее, пожалуйста, дайте мне знать. - person fmalina; 02.02.2011
comment
вы можете кэшировать результат, сохранять агрегаты в их собственной модели, запускать какую-то фоновую агрегацию и тому подобное... - person tijs; 15.08.2012