Customizing Filter Form

Customizing Filter Form#

The filter form is a form that is used to filter the data to be used in the report.

The generated form#

Behind the scene, The view calls slick_reporting.form_factory.report_form_factory in get_form_class method. report_form_factory is a helper method which generates a form containing start date and end date, as well as all foreign keys on the report_model.

Changing the generated form API is still private, however, you can use your own form easily.

Overriding the Form#

The system expect that the form used with the ReportView to implement the slick_reporting.forms.BaseReportForm interface.

The interface is simple, only 3 mandatory methods to implement, The rest are mandatory only if you are working with a crosstab report or a time series report.

  • get_filters: Mandatory, return a tuple (Q_filters , kwargs filter) to be used in filtering. q_filter: can be none or a series of Django’s Q queries kwargs_filter: None or a dictionary of filters

  • get_start_date: Mandatory, return the start date of the report.

  • get_end_date: Mandatory, return the end date of the report.

  • get_crispy_helper : Optional, return a crispy form helper to be used in rendering the form.

In case you are working with a crosstab report, you need to implement the following methods:

  • get_crosstab_compute_remainder: return a boolean indicating if the remainder should be computed or not.

  • get_crosstab_ids: return a list of ids to be used in the crosstab report.

And in case you are working with a time series report, with a selector on, you need to implement the following method:

  • get_time_series_pattern: return a string representing the time series pattern. ie: ie: daily, monthly, yearly

Example a full example of a custom form:

# forms.py
from slick_reporting.forms import BaseReportForm

# A Normal form , Inheriting from BaseReportForm
class RequestLogForm(BaseReportForm, forms.Form):

    SECURE_CHOICES = (
        ("all", "All"),
        ("secure", "Secure"),
        ("non-secure", "Not Secure"),
    )

    start_date = forms.DateField(
        required=False,
        label="Start Date",
        widget=forms.DateInput(attrs={"type": "date"}),
    )
    end_date = forms.DateField(
        required=False, label="End Date", widget=forms.DateInput(attrs={"type": "date"})
    )
    secure = forms.ChoiceField(
        choices=SECURE_CHOICES, required=False, label="Secure", initial="all"
    )
    method = forms.CharField(required=False, label="Method")
    response = forms.ChoiceField(
        choices=HTTP_STATUS_CODES,
        required=False,
        label="Response",
        initial="200",
    )
    other_people_only = forms.BooleanField(
        required=False, label="Show requests from other People Only"
    )

    def __init__(self, *args, **kwargs):
        super(RequestLogForm, self).__init__(*args, **kwargs)
        # provide initial values and ay needed customization
        self.fields["start_date"].initial = datetime.date.today()
        self.fields["end_date"].initial = datetime.date.today()

    def get_filters(self):
        # return the filters to be used in the report
        # Note: the use of Q filters and kwargs filters
        filters = {}
        q_filters = []
        if self.cleaned_data["secure"] == "secure":
            filters["is_secure"] = True
        elif self.cleaned_data["secure"] == "non-secure":
            filters["is_secure"] = False
        if self.cleaned_data["method"]:
            filters["method"] = self.cleaned_data["method"]
        if self.cleaned_data["response"]:
            filters["response"] = self.cleaned_data["response"]
        if self.cleaned_data["other_people_only"]:
            q_filters.append(~Q(user=self.request.user))

        return q_filters, filters

    def get_start_date(self):
        return self.cleaned_data["start_date"]

    def get_end_date(self):
        return self.cleaned_data["end_date"]

    # ----
    # in views.py

    from .forms import RequestLogForm

    class RequestCountByPath(ReportView):
        form_class = RequestLogForm

You can view this code snippet in action on the demo project https://django-slick-reporting.com/total-product-sales-with-custom-form/