RamezIssac / django-slick-reporting

The Reporting Engine for Django. Create dashboards and standalone Reports and Charts.

Home Page:https://django-slick-reporting.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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 :)

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!