Datetime to date casting in group_by?
vaughnd opened this issue · comments
Hi,
I'm trying to build a simple report showing a count of Users grouped by date_joined but at a daily level. I need to cast date_joined from a datetime to a date first, but all the routes I've tried aren't working:
- date_joined__date errors out in slick reports because it thinks it's a relation instead of a Django function
- TruncDate I can't get working, because I can't have an empty columns field and referencing it in columns gets the error 'django.core.exceptions.FieldDoesNotExist: Field "date_joined_date" not found either as an attribute to the generator class <class 'slick_reporting.generator.ReportGenerator'>, Container class <class 'analytics.views.NewUsersReportView'>,or a computation field, or a database column for the model "<class 'core.models.models_user.User'>"'
- Trying to use a SlickReportField as the column for the TruncDate above also fails because it expects a method.
It feels like I'm making this far more complex than it should be, so was hoping for some expert guidance please :)
Two options I've been trying are below. I was hoping the first would work as I prefer the simplicity.
class NewUsersReportView(SlickReportView):
report_model = User
group_by = 'date_joined__date'
date_field = 'date_joined'
columns = [
"date_joined__date",
SlickReportField.create(method=Count, field='id', name='count_users', verbose_name='Users')
]
chart_settings = [{
'type': 'column',
'data_source': ['count_users'],
'title_source': 'date_joined_date',
'title': 'Date Joined',
}, ]
class NewUsersReportView(SlickReportView):
report_model = User
date_field = 'date_joined'
columns = [
"date_joined_date",
SlickReportField.create(method=Count, field='id', name='count_users', verbose_name='Users')
]
chart_settings = [{
'type': 'column',
'data_source': ['count_users'],
'title_source': 'date_joined_date',
'title': 'Date Joined',
}, ]
def get_data(self):
queryset = self.get_queryset()
queryset = queryset.annotate(date_joined_date=TruncDate('date_joined'))
queryset = queryset.values('date_joined_date').annotate(count=Count('id'))
queryset = queryset.order_by('date_joined_date')
return queryset
Hello @vaughnd
I get what you're trying to do... Thank you for the helpful code!
Will get back to you
So, what you want to do is actually a time series report
The below example should get you the results you want ..
class NewUsersReportViewTimeSeries(SlickReportView):
report_model = User
date_field = "date_joined"
# we will remove this because we want the results on the whole set.
# group_by = "..."
time_series_pattern = "daily"
time_series_columns = [
SlickReportField.create(
method=Count, field="id", name="count_users", verbose_name="Users"
)
]
columns = [
"__time_series__",
# this column would be the total count users joined in the set, a Sum of the time series shown before.
# SlickReportField.create(
# method=Count, field="id", name="total_count_users", verbose_name="Users"
# )
]
chart_settings = [
{
"type": "column",
"data_source": ["count_users"],
"title_source": "date_joined_date",
"title": "Date Joined",
},
]
Let me know how it goes :)
Time series options https://django-slick-reporting.readthedocs.io/en/latest/time_series_options.html
Just added this to the docs ..
Thanks. It kind of got the results I needed, but I think I'm going to need to look at using Metabase instead. Nice work on Slick reporting though, definitely the most advanced and user-friendly Django lib out there!