def count(self, request, **kwargs): query_params = request.query_params.copy() material = query_params.pop('material', None) include_children = query_params.pop('include_child_materials', None) queryset = self._filter(kwargs, query_params=query_params) if (material is not None): mat_id = material[0] if include_children: mats = Material.objects.filter( id__in=descend_materials([Material.objects.get( id=mat_id)])) queryset = queryset.filter(strategy_material__in=mats) else: queryset = queryset.filter(strategy_material=mat_id) if ('origin_area' in request.data): geojson = self.request.data['origin_area'] poly = GEOSGeometry(geojson) queryset = queryset.filter( origin__administrative_location__geom__intersects=poly) if ('destination_area' in request.data): geojson = self.request.data['destination_area'] poly = GEOSGeometry(geojson) queryset = queryset.filter( destination__administrative_location__geom__intersects=poly) json = {'count': queryset.count()} return Response(json)
def _get_referenced_flows(self, flow_reference, implementation): ''' return flows on actor level filtered by flow_reference attributes and implementation areas ''' origins, destinations = self._get_actors(flow_reference, implementation) flows = get_annotated_fractionflows(self.strategy.keyflow.id, self.strategy.id) flows = flows.filter(origin__in=origins, destination__in=destinations) if flow_reference.include_child_materials: impl_materials = Material.objects.filter( id__in=descend_materials([flow_reference.material])) kwargs = {'strategy_material__in': impl_materials} else: kwargs = {'strategy_material': flow_reference.material.id} if flow_reference.process: kwargs['strategy_process'] = flow_reference.process.id reference_flows = flows.filter(**kwargs) return reference_flows
def post_get(self, request, **kwargs): ''' body params: body = { # prefilter flows # list of subfilters, subfilters are 'and' linked # keys: django filter function (e.g. origin__id__in) # values: values for filter function (e.g. [1,5,10]) filters: [ { link : 'and' or 'or' (default 'and'), some-django-filter-function: value, another-django-filter-function: value }, { link: ... }, .... ], filter_link: and/or, # logical linking of filters, defaults to 'or' # filter/aggregate by given material materials: { ids: [...], # ids of materials to filter, only flows with those materials and their children will be returned, other materials will be ignored unaltered: [...], # ids of materials that should be kept as they are when aggregating aggregate: true / false, # if true the children of the given materials will be aggregated, aggregates to top level materials if no ids were given }, anonymize: true/false, # anonymize the actor names # exclusive to spatial_level aggregation_level: { origin: 'activity' or 'activitygroup', defaults to actor level destination: 'activity' or 'activitygroup', defaults to actor level } } ''' self.check_permission(request, 'view') strategy_id = request.query_params.get('strategy', None) if strategy_id is not None: strategy = Strategy.objects.get(id=strategy_id) if strategy.status == 0: return HttpResponseBadRequest(_('calculation is not done yet')) if strategy.status == 1: return HttpResponseBadRequest( _('calculation is still in process')) # filter by query params queryset = self._filter(kwargs, query_params=request.query_params, SerializerClass=self.get_serializer_class()) # filter flows between included actors (resp. origin only if stock) queryset = queryset.filter( Q(origin__included=True) & (Q(destination__included=True) | Q(destination__isnull=True))) params = {} # values of body keys are not parsed for key, value in request.data.items(): try: params[key] = json.loads(value) except json.decoder.JSONDecodeError: params[key] = value filter_chains = params.get('filters', None) material_filter = params.get('materials', None) l_a = params.get('aggregation_level', {}) inv_map = {v: k for k, v in LEVEL_KEYWORD.items()} origin_level = inv_map[l_a['origin']] if 'origin' in l_a else Actor destination_level = inv_map[l_a['destination']] \ if 'destination' in l_a else Actor keyflow = kwargs['keyflow_pk'] # filter queryset based on passed filters if filter_chains: queryset = self.filter_chain(queryset, filter_chains, keyflow) aggregate_materials = (False if material_filter is None else material_filter.get('aggregate', False)) material_ids = (None if material_filter is None else material_filter.get('ids', None)) unaltered_material_ids = ([] if material_filter is None else material_filter.get('unaltered', [])) materials = None unaltered_materials = [] # filter the flows by their fractions excluding flows whose # fractions don't contain the requested materials # (including child materials) if material_ids is not None: materials = Material.objects.filter(id__in=material_ids) unaltered_materials = Material.objects.filter( id__in=unaltered_material_ids) mats = descend_materials( list(materials) + list(unaltered_materials)) queryset = queryset.filter( strategy_material__in=Material.objects.filter(id__in=mats)) agg_map = None try: if aggregate_materials: agg_map = self.map_aggregation( queryset, materials, unaltered_materials=unaltered_materials) except RecursionError as e: return HttpResponse(content=str(e), status=500) data = self.serialize(queryset, origin_model=origin_level, destination_model=destination_level, aggregation_map=agg_map) return Response(data)
def get_queryset(self, indicator_flow, geom=None): '''filter all flows by IndicatorFlow attributes, optionally filter for geometry''' # there might be unset indicators -> return empty queryset # (calculation will return zero) if not indicator_flow: return FractionFlow.objects.none() materials = indicator_flow.materials.all() flow_type = indicator_flow.flow_type.name hazardous = indicator_flow.hazardous.name avoidable = indicator_flow.avoidable.name flows = get_fractionflows(self.keyflow_pk, strategy=self.strategy) # filter flows by type (waste/product/both) if flow_type != 'BOTH': is_waste = True if flow_type == 'WASTE' else False flows = flows.filter(strategy_waste=is_waste) if hazardous != 'BOTH': is_hazardous = True if hazardous == 'YES' else False flows = flows.filter(strategy_hazardous=is_hazardous) if avoidable != 'BOTH': is_avoidable = True if avoidable == 'YES' else False flows = flows.filter(strategy_avoidable=is_avoidable) # filter flows by processes process_ids = indicator_flow.process_ids if (process_ids): process_ids = process_ids.split(',') processes = Process.objects.filter(id__in=process_ids) flows = flows.filter(strategy_process__in=processes) if materials: mats = descend_materials(list(materials)) mats = Material.objects.filter(id__in=mats) flows = flows.filter(strategy_material__in=mats) # ToDo: implement new filter attribute sinks and sources only #destinations_to_exclude = flows.exclude(destination__isnull=True).values('destination__id').distinct() ##flows_to_exclude = flows.filter(origin__in=destinations_to_exclude) #flows2 = flows.exclude(origin__id__in=destinations_to_exclude) # filter flows by origin/destination nodes origin_node_ids = indicator_flow.origin_node_ids origin_node_ids = origin_node_ids.split(',') \ if len(origin_node_ids) > 0 else [] destination_node_ids = indicator_flow.destination_node_ids destination_node_ids = destination_node_ids.split(',') \ if len(destination_node_ids) > 0 else [] origins = self.get_actors(origin_node_ids, indicator_flow.origin_node_level) destinations = self.get_actors(destination_node_ids, indicator_flow.destination_node_level) if geom: spatial = indicator_flow.spatial_application.name if spatial == 'ORIGIN' or spatial == 'BOTH': origins = filter_actors_by_area(origins, geom) if spatial == 'DESTINATION' or spatial == 'BOTH': destinations = filter_actors_by_area(destinations, geom) flows = flows.filter( Q(origin__in=origins) & Q(destination__in=destinations)) return flows