Computation Field API
Responsible for preforming the calculation.
ReportField Basic Structure:
Earlier in he docs you saw the computation fields
Let’s see how it’s written in slick_reporting.fields
from slick_reporting.fields import SlickReportField from slick_reporting.decorators import report_field_register @report_field_register class TotalQTYReportField(SlickReportField): # The name to use when using this field in the generator name = '__total_quantity__' # the field we want to compute on calculation_field = 'quantity' # What method we want calculation_method = Sum # the default # A verbose name verbose name = 'Total quantity'
If you want AVG to the field price then the ReportField would look like this
from django.db.models import Avg @report_field_register class TotalQTYReportField(SlickReportField): name = '__avg_price__' calculation_field = 'price' calculation_method = Avg verbose name = 'Avg. Price'
How it works ?
The ReportGenerator is initialized with the needed configuration, it generates a list of the needed fields to be displayed and computed. For each computation field, it’s given the filters needed and asked to get all the results prepared. The preparation is a duty of the ReportField anyway, then for each report_model record, the ReportGenerator again asks each ComputationField to get the data it has for each record and map it where it belongs.
Bundled Report Fields
__total__ : Sum of the field names value
__total_quantity__ :Sum of the field names ‘quantity’
__fb__ : Sum of the field value on the start date (or the start date of the active time series window)
__balance__: Compound some of the field value .
Difference between total and balance is:
The field __total__ will return that client 1 bought 10 in Jan, 12 in Feb , 13 in March. while __balance__ will report client compound buy: 10 in Jan, 22 in Feb and 35 in March
Registering Report Field
To make this ReportField class available to the report, it has to be registered via
Say you want to further customize your calculation, maybe you need to run a complex query
You can override both of those method and control the calculation
Two side calculation
# todo: # Document how a single field can be computed like a debit and credit.
- class slick_reporting.fields.SlickReportField(plus_side_q=None, minus_side_q=None, report_model=None, qs=None, calculation_field=None, calculation_method=None, date_field='', group_by=None)
Computation field responsible for making the calculation unit
- name = ''
The name to be used in the ReportGenerator
- calculation_field = 'value'
the Field to compute on
- calculation_method = <class 'django.db.models.aggregates.Sum'>
The computation Method
- verbose_name = None
Verbose name to be used in front end when needed
- requires = None
This can be a list of sibling classes, they will be asked to compute and their value would be available to you in the resolve method requires = [BasicCalculationA, BasicCalculationB]
- type = 'number'
Just a string describing what this computation field return, usually passed to frontend
Below are some data passed by the ReportGenerator, for extra manipulation, you can change them
- report_model = None
- group_by = None
- plus_side_q = None
- minus_side_q = None
You can customize those methods for maximum control where you can do pretty much whatever you want.
- prepare(q_filters=None, kwargs_filters=None, **kwargs)
This is the first hook where you can customize the calculation away from the Django Query aggregation method This method et called with all available parameters , so you can prepare the results for the whole set and save it in a local cache (like self._cache) . The flow will later call the method resolve, giving you the id, for you to return it respective calculation
- resolve(current_obj, current_row=None)
Reponsible for getting the exact data from the prepared value :param cached: the returned data from prepare :param current_obj: he value of group by id :param current_row: the row in iteration :return: a solid number or value
- get_dependency_value(current_obj, name=None)
Get the values of the ReportFields specified in requires
current_obj – the current object which we want the calculation for
name – Optional, the name of the specific dependency you want.
a dict containing dependencies names as keys and their calculation as values or a specific value if name is specified.