def filter(self, qs): filterscount = int(self.request.GET.get('filterscount', 0)) # server-side filtering if filterscount: filters = dict() for filter_num in range(filterscount): num = str(filter_num) field = self.request.GET.get('filterdatafield' + num).replace( '-', '_') field = self.field_name_transform_map.get(field, field) value = (self.get_field_types() or self.field_types).get( field, str)(self.request.GET.get('filtervalue' + num)) condition = self.request.GET.get('filtercondition' + num) op = int(self.request.GET.get('filteroperator' + num, 0)) if not filters.get(field): filters[field] = list() filters[field].append( dict(value=value, condition=condition, operator=op)) q_all = Q() q_all.op = 1 # 0 - AND, 1 - OR for field in filters: for field_condition in filters[field]: cond = field_condition['condition'] val = field_condition['value'] op = field_condition['operator'] # 0 - AND, 1 - OR q_curr = Q() # TODO: check if bool/null filter improved in new jqWidgets grid # if vale is False filter None and False if (self.get_field_types() or self.field_types).get( field, str).__name__ == 'bool_lookup': if cond == 'NOT_EQUAL' and val is True or cond == 'EQUAL' and val is False: q_curr = Q(**{field: False}) | Q( **{'%s__isnull' % field: True}) else: q_curr = Q(**{field: True}) elif cond in self.conditions: cond_str = '%s__%s' % (field, self.conditions[cond]) q_curr = Q(**{cond_str: val}) elif cond in self.conditions_empty: cond_str = '%s__%s' % (field, self.conditions_empty[cond][0]) val = self.conditions_empty[cond][1] q_curr = Q(**{cond_str: val}) elif cond in self.conditions_neg: cond_str = '%s__%s' % (field, self.conditions_neg[cond]) q_curr = ~Q(**{cond_str: val}) # filter out empty and None values as well elif cond == 'NOT_EMPTY': q_curr = ~Q(**{field: ''}) & Q( **{'%s__isnull' % field: False}) q_all = q_all | q_curr if q_all.op else q_all & q_curr q_all.op = op qs = qs.filter(q_all) return qs
def get_queryset(self): filters = self.get_entries_filters() queryset = get_filtered_entries(self.request.user, filters).select_related( 'lead', 'lead__attachment', 'controlled_changed_by', ).prefetch_related('lead__assignee') queryset = Entry.annotate_comment_count(queryset) project = filters.get('project') search = filters.get('search') if search: # For searching tabular columns field_filters = {} if project: field_filters['sheet__book__project'] = project fields = TabularField.objects.filter(title__icontains=search, **field_filters) queryset = queryset.filter( models.Q(lead__title__icontains=search) | models.Q(excerpt__icontains=search) | (models.Q(tabular_field__in=models.Subquery( fields.values_list('pk', flat=True))))) return (queryset.select_related( 'image', 'lead', 'created_by__profile', 'modified_by__profile', ).prefetch_related( 'attribute_set', 'lead__authors', 'lead__assignee', 'lead__assignee__profile', 'lead__leadpreview', ))
def read_request_filters(self) -> Dict[str, Any]: filterscount = int(self.request.GET.get('filterscount', 0)) # server-side filtering filters = dict() if filterscount: for filter_num in range(filterscount): num = str(filter_num) field = self.request.GET.get('filterdatafield' + num).replace('-', '_') field = self.field_name_transform_map.get(field, field) value = (self.get_field_types() or self.field_types).get(field, str)( self.request.GET.get('filtervalue' + num)) condition = self.request.GET.get('filtercondition' + num) op = int(self.request.GET.get('filteroperator' + num, 0)) if not filters.get(field): filters[field] = list() filters[field].append(dict(value=value, condition=condition, operator=op)) return filters
def post(self, request, version=None): filters = request.data.get('filters', []) filters = {f[0]: f[1] for f in filters} queryset = get_filtered_entries(request.user, filters) search = filters.get('search') if search: queryset = queryset.filter( models.Q(lead__title__icontains=search) | models.Q(excerpt__icontains=search)) queryset = EntryFilterSet(filters, queryset=queryset).qs page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return response.Response(serializer.data)
def get_counts_by_matrix_2d(self, qs): # Project should be provided filters = self.get_entries_filters() project = filters.get('project') if project is None: return {} # Pull necessary widgets widgets = Widget.objects.filter(analysis_framework__project=project, widget_id__in=[ matrix1d_widget.WIDGET_ID, matrix2d_widget.WIDGET_ID ]).values_list('key', 'widget_id', 'properties') # Pull necessary filters filters = { filter.key: filter for filter in Filter.objects.filter( analysis_framework__project=project, key__in=[ _key for key, widget_id, _ in widgets for _key in ( [f'{key}-dimensions', f'{key}-sectors'] if widget_id == matrix2d_widget.WIDGET_ID else [key]) ]) } # Calculate count agg_data = qs.aggregate( **{ f"{key}__{ele['id' if widget_id == matrix2d_widget.WIDGET_ID else 'key']}__{control_status}": models.Count( 'id', filter=models.Q( controlled=control_status == 'controlled', filterdata__filter=( filters[f'{key}-{data_type}' if widget_id == matrix2d_widget.WIDGET_ID else key]), filterdata__values__contains=[ ele['id' if widget_id == matrix2d_widget.WIDGET_ID else 'key'] ], ), distinct=True, ) for key, widget_id, properties in widgets for data_type in (['sectors', 'dimensions'] if widget_id == matrix2d_widget.WIDGET_ID else ['rows']) for _ele in properties['data'][data_type] for ele in [ _ele, *( _ele.get(f'sub{data_type}' if widget_id == matrix2d_widget.WIDGET_ID else 'cells') or []) ] for control_status in ['controlled', 'uncontrolled'] }) # Re-structure data (also snake-case to camel case conversion will change the key) response = defaultdict(lambda: defaultdict(lambda: defaultdict(int))) for key, count in agg_data.items(): widget_key, label_key, controlled_status = key.split('__') response[widget_key][label_key][controlled_status] = count return [{ 'widget_key': widget_key, 'label_key': label_key, 'controlled_count': count['controlled'], 'uncontrolled_count': count['uncontrolled'], } for widget_key, widget_data in response.items() for label_key, count in widget_data.items()]