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)
Exemple #2
0
 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)
Exemple #4
0
    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