The goal of django-qsstats is to be a microframework to make repetitive tasks such as generating aggregate statistics of querysets over time easier. It's probably overkill for the task at hand, but yay microframeworks!
- python-dateutil
- django 1.1+
Liensed under a BSD-style license.
from django.contrib.auth import User import qsstats qs = User.objects.all() qss = qsstats.QuerySetStats(qs, 'date_joined') print '%s new accounts today.' % qss.this_day() print '%s new accounts this month.' % qss.this_month() print '%s new accounts this year.' % qss.this_year() print '%s new accounts until now.' % qss.until_now()
This might print something like:
5 new accounts today. 27 new accounts this month. 377 new accounts this year. 409 new accounts until now.
from django.contrib.auth import User import datetime, qsstats qs = User.objects.all() qss = qsstats.QuerySetStats(qs, 'date_joined') today = datetime.date.today() seven_days_ago = today - datetime.timedelta(days=7) time_series = qss.time_series(seven_days_ago, today) print 'New users in the last 7 days: %s' % [t[1] for t in time_series]
This might print something like:
New users in the last 7 days: [3, 10, 7, 4, 12, 9, 11]
Please see qsstats/tests.py for similar usage examples.
In order to provide maximum flexibility, the QuerySetStats
object
can be instantiated with as little or as much information as you like.
All keword arguments are optional but DateFieldMissing
and
QuerySetMissing
will be raised if you try to use QuerySetStats
without providing enough information.
qs
The queryset to operate on.
Default:
None
date_field
The date field within the queryset to use.
Default:
None
aggregate_field
The field to use for aggregate data. Can be set system-wide with the setting
QUERYSETSTATS_DEFAULT_AGGREGATE_FIELD
or set when instantiating or calling one of the methods.Default:
'id'
aggregate_class
The aggregate class to be called during aggregation operations. Can be set system-wide with the setting
QUERYSETSTATS_DEFAULT_AGGREGATE_CLASS
or set when instantiating or calling one of the methods.Default:
Count
operator
The default operator to use for the
pivot
function. Can be set system-wide with the settingQUERYSETSTATS_DEFAULT_OPERATOR
or set when callingpivot
.Default:
'lte'
All of the documented methods take a standard set of keyword arguments that override any information already stored within the QuerySetStats
object. These keyword arguments are date_field
, aggregate_field
, aggregate_class
.
Once you have a QuerySetStats
object instantiated, you can receive a single aggregate result by using the following methods:
for_day
- Positional arguments:
dt
, adatetime.datetime
ordatetime.date
object to filter the queryset to this day. this_day
- A wrapper around
for_day
that provides aggregate information fordatetime.date.today()
. It takes no positional arguments. for_month
- Positional arguments:
dt
, adatetime.datetime
ordatetime.date
object to filter the queryset to this month. this_month
- A wrapper around
for_month
that usesdateutil.relativedelta
to provide aggregate information for this current month. for_year
- Positional arguments:
dt
, adatetime.datetime
ordatetime.date
object to filter the queryset to this year. this_year
- A wrapper around
for_year
that usesdateutil.relativedelta
to provide aggregate information for this current year.
QuerySetStats
also provides a method for returning aggregated
time-series data which may be extremely using in plotting data:
time_series
Positional arguments:
start_date
andend_date
, each adatetime.date
ordatetime.datetime
object used in marking the start and stop of the time series data.Keyword arguments: In addition to the standard
date_field
,aggregate_field
, andaggregate_class
keyword argument,time_series
takes an optionalinterval
keyword argument used to mark which interval to use while calculating aggregate data betweenstart_date
andend_date
. This argument defaults to'days'
and can accept'years'
,'months'
,'weeks'
, or'days'
. It will raiseInvalidInterval
otherwise.This methods returns a list of tuples. The first item in each tuple is a
datetime.date
object for the current inverval. The second item is the result of the aggregate operation. For example:[(datetime.date(2010, 3, 28), 12), (datetime.date(2010, 3, 29), 0), ...]
Formatting of date information is left as an exercise to the user and may vary depending on interval used.
until
Provide aggregate information until a given date or time, filtering the queryset using
lte
.Positional arguments:
dt
adatetime.date
ordatetime.datetime
object to be used for filtering the queryset since.Keyword arguments:
date_field
,aggregate_field
,aggregate_class
.until_now
Aggregate information until now.
Positional arguments:
dt
adatetime.date
ordatetime.datetime
object to be used for filtering the queryset since (usinglte
).Keyword arguments:
date_field
,aggregate_field
,aggregate_class
.after
Aggregate information after a given date or time, filtering the queryset using
gte
.Positional arguments:
dt
adatetime.date
ordatetime.datetime
object to be used for filtering the queryset since.Keyword arguments:
date_field
,aggregate_field
,aggregate_class
.after_now
Aggregate information after now.
Positional arguments:
dt
adatetime.date
ordatetime.datetime
object to be used for filtering the queryset since (usinggte
).Keyword arguments:
date_field
,aggregate_field
,aggregate_class
.pivot
Used by
since
,after
, anduntil_now
but potentially useful if you would like to specify your own operator instead of the defaults.Positional arguments:
dt
adatetime.date
ordatetime.datetime
object to be used for filtering the queryset since (usinglte
).Keyword arguments:
operator
,date_field
,aggregate_field
,aggregate_class
.Raises
InvalidOperator
if the operator provided is not one of'lt'
,'lte'
,gt
orgte
.
If you'd like to test django-qsstats
against your local configuration, add
qsstats
to your INSTALLED_APPS
and run ./manage.py test qsstats
. The test suite assumes that django.contrib.auth
is installed.
- There's a bunch of boilerplate that I'm sure could be reduced.
- Clearer documentation and usage examples.
- More test coverage.