Ejemplo n.º 1
0
    def get(self, request, **kwargs):

        # try to use qprof api
        # ====================

        # try to load layer
        try:
            epp = EleProDTM.objects.get(pk=kwargs['eleprodtm_pk'])
            layer = epp.layers.filter(qgs_layer_id=kwargs['qgs_layer_id'])[0]
            dem = epp.dtm_layer
        except KeyError:
            # Case qgs_layer_id not submit
            raise APIException('No qgs_layer_id parameter into url')
        except ObjectDoesNotExist as e:
            raise APIException('DTM project object not found into DB')
        except IndexError as e:
            raise APIException('Layer not set into a profile project')

        # try to get qgis_layer
        qgis_project = get_qgs_project(dem.project.qgis_file.path)
        qgis_dem = get_qgis_layer(dem)
        qgis_layer = get_qgis_layer(layer)

        # get single feature
        feature = qgis_layer.getFeature(kwargs['fid'])
        geom = feature.geometry()
        if not geom:
            raise APIException('Fid not found into layer')

        if geom.isMultipart():
            line = multipolyline_to_xytuple_list2(
                geom.asMultiPolyline())  # typedef QVector<QgsPolyline>
            # now it's a list of list of (x,y) tuples
            path_line = xytuple_l2_to_MultiLine(line).to_line()

        else:
            line = polyline_to_xytuple_list(
                geom.asPolyline())  # typedef QVector<QgsPointXY>
            path_line = xytuple_list_to_Line(line)

        multi_path_line = MultiLine([path_line
                                     ]).to_line().remove_coincident_points()

        # line resampled by sample distance
        resampled_line = multi_path_line.densify_2d_line(epp.dtm_delta)

        if qgis_layer.crs() != qgis_project.crs():
            resampled_line = resampled_line.crs_project(
                qgis_layer.crs(), qgis_project.crs())

        profile = topoline_from_dem(
            resampled_line, True, qgis_project.crs(), qgis_dem,
            QGisRasterParameters(*raster_qgis_params(qgis_dem)), epp.dtm_delta)

        self.results.update({'profile': profile})

        return Response(self.results.results)
Ejemplo n.º 2
0
    def apply_filter(self,
                     request,
                     metadata_layer,
                     qgis_feature_request,
                     view=None):
        """Apply the filter to the QGIS feature request or the layer's subset string
        Warning: if the filter alters the layer instance (for example by settings a subset
        string) make sure to restore the original state or to work on a clone.
        """

        qgis_layer = metadata_layer.qgis_layer

        expression_text = None
        if FILTER_RELATIONONETOMANY_PARAM not in request.GET \
                or request.GET[FILTER_RELATIONONETOMANY_PARAM] == '':
            return
        else:
            try:
                relation_id, parent_serverFid = request.GET[
                    FILTER_RELATIONONETOMANY_PARAM].split('|')
            except ValueError as e:
                logger.error('RelationOneToManyFilter: %s' % (e, ))
                return

        if not relation_id or not parent_serverFid:
            return

        # get QgsRelation object
        qgs_prj = get_qgs_project(view.layer.project.qgis_file.path)
        qgs_relation = qgs_prj.relationManager().relation(relation_id)

        if not qgs_relation.isValid():
            return

        # get expression
        try:
            expression = expression_from_server_fids(
                [parent_serverFid],
                qgs_relation.referencedLayer().dataProvider())
            feature = next(qgs_relation.referencedLayer().getFeatures(
                QgsFeatureRequest(QgsExpression(expression))))
            expression_text = qgs_relation.getRelatedFeaturesFilter(feature)
        except StopIteration:
            logger.error(
                'RelationOneToManyFilter: error finding related feature from expression'
            )
            return

        if not expression_text:
            logger.error(
                'RelationOneToManyFilter: empty related feature expression filter'
            )
            return

        qgis_feature_request.combineFilterExpression(expression_text)
Ejemplo n.º 3
0
    def apply_filter(self,
                     request,
                     qgis_layer,
                     qgis_feature_request,
                     view=None):
        """Apply the filter to the QGIS feature request or the layer's subset string
        Warning: if the filter alters the layer instance (for example by settings a subset
        string) make sure to restore the original state or to work on a clone.
        """

        expression_text = None
        if FILTER_RELATIONONETOMANY_PARAM not in request.GET \
                or request.GET[FILTER_RELATIONONETOMANY_PARAM] == '':
            return
        else:
            try:
                relation_id, parent_fid = request.GET[
                    FILTER_RELATIONONETOMANY_PARAM].split('|')
            except ValueError as e:
                logger.error('RelationOneToManyFilter: %s' % (e, ))
                return

        if not relation_id or not parent_fid:
            return

        # get QgsRelation object
        qgs_prj = get_qgs_project(view.layer.project.qgis_file.path)
        qgs_relation = qgs_prj.relationManager().relation(relation_id)

        if not qgs_relation.isValid():
            return

        # get expression
        expression_text = qgs_relation.getRelatedFeaturesFilter(
            qgs_relation.referencedLayer().getFeature(int(parent_fid)))

        if not expression_text:
            return

        original_expression = qgis_feature_request.filterExpression(
        ) if qgis_feature_request is not None else None
        if original_expression is not None:
            qgis_feature_request.setFilterExpression(
                "({original_expression}) AND ({extra_expression})".format(
                    original_expression=original_expression.expression(),
                    extra_expression=expression_text))
        else:
            qgis_feature_request.setFilterExpression(expression_text)
Ejemplo n.º 4
0
    def test_filtertoken_api(self):
        """ Test vector layer api data with 'filtertoken' param """

        cities = Layer.objects.get(project_id=self.project310.instance.pk,
                                   origname='cities10000eu')
        qgis_project = get_qgs_project(cities.project.qgis_file.path)
        qgis_layer = qgis_project.mapLayer(cities.qgs_layer_id)

        # create a token filter
        admin01 = self.test_user1
        session_token = SessionTokenFilter.objects.create(user=admin01)
        session_filter = session_token.stf_layers.create(
            layer=cities, qgs_expr="ISO2_CODE = 'IT'")

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'filtertoken': session_token.token
            }).content)

        self.assertEqual(resp['vector']['count'], 1124)

        # update token filer
        session_filter.qgs_expr = "ISO2_CODE = 'XXXXX'"
        session_filter.save()

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'filtertoken': session_token.token
            }).content)

        self.assertEqual(resp['vector']['count'], 0)

        # submit a fake token/ filter token of other layer
        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'filtertoken': 'xxxxxxxxxxxxxx'
            }).content)

        self.assertEqual(resp['vector']['count'], 8965)
Ejemplo n.º 5
0
    def test_relationonetomany_api(self):
        """ Test relationonetomany filter """

        cities = Layer.objects.get(project_id=self.project310.instance.pk,
                                   origname='cities10000eu')
        qgis_project = get_qgs_project(cities.project.qgis_file.path)
        qgis_layer = qgis_project.mapLayer(cities.qgs_layer_id)

        total_count = qgis_layer.featureCount()

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                FILTER_RELATIONONETOMANY_PARAM: ''
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)

        # check filter by relations

        resp = json.loads(
            self._testApiCall(
                'core-vector-api', [
                    'data', 'qdjango', self.project310.instance.pk,
                    cities.qgs_layer_id
                ], {
                    FILTER_RELATIONONETOMANY_PARAM:
                    'cities1000_ISO2_CODE_countries__ISOCODE|18'
                }).content)

        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression('"ISO2_CODE" = \'IT\'')
        qgis_layer.selectByExpression(
            qgs_request.filterExpression().expression())

        features = qgis_layer.getFeatures(qgs_request)
        self.assertEqual(resp['vector']['count'], len([f for f in features]))
Ejemplo n.º 6
0
    def test_unique_request_api_param(self):
        """ Test 'unique' url request param for 'data' vector API """

        cities = Layer.objects.get(project_id=self.project310.instance.pk,
                                   origname='cities10000eu')
        qgis_project = get_qgs_project(cities.project.qgis_file.path)
        qgis_layer = qgis_project.mapLayer(cities.qgs_layer_id)

        # check for only unique param
        total_count = len(
            qgis_layer.uniqueValues(qgis_layer.fields().indexOf('ISO2_CODE')))

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'unique': 'ISO2_CODE'
            }).content)

        self.assertEqual(resp['count'], total_count)

        # check SuggestFilterBackend + FieldFilterBackend
        # -----------------------------------------------

        resp = json.loads(
            self._testApiCall(
                'core-vector-api', [
                    'data', 'qdjango', self.project310.instance.pk,
                    cities.qgs_layer_id
                ], {
                    'suggest': 'NAME|flo',
                    'field': 'ISO2_CODE|eq|IT',
                    'unique': 'ISO2_CODE'
                }).content)

        self.assertEqual(resp['count'], 1)
Ejemplo n.º 7
0
    def test_server_filters_combination_api(self):
        """ Test server filter combination: i.e. FieldFilterBacked + SuggestFilterBackend """

        cities = Layer.objects.get(project_id=self.project310.instance.pk,
                                   origname='cities10000eu')
        qgis_project = get_qgs_project(cities.project.qgis_file.path)
        qgis_layer = qgis_project.mapLayer(cities.qgs_layer_id)

        # check FieldFilterBacked
        # -----------------------
        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression('"ISO2_CODE" = \'IT\'')
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'field': 'ISO2_CODE|eq|IT'
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)

        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression(
            '"ISO2_CODE" = \'IT\' OR "ISO2_CODE" = \'FR\'')
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'field': 'ISO2_CODE|eq|IT|OR,ISO2_CODE|eq|FR'
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)

        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression(
            '"ISO2_CODE" = \'IT\' AND "POPULATION" > 10000 OR "ISO2_CODE" = \'FR\''
        )
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall(
                'core-vector-api', [
                    'data', 'qdjango', self.project310.instance.pk,
                    cities.qgs_layer_id
                ], {
                    'field':
                    'ISO2_CODE|eq|IT|AND,POPULATION|gt|10000|OR,ISO2_CODE|eq|FR',
                }).content)

        self.assertEqual(resp['vector']['count'], total_count)

        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression('"NAME" LIKE \'%Flo%\'')
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'field': 'NAME|like|Flo'
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)

        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression('"NAME" ILIKE \'%flo%\'')
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'field': 'NAME|ilike|flo'
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)

        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression(
            '"ISO2_CODE" = \'IT\' AND "NAME" = \'Florence\'')
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'field': 'ISO2_CODE|eq|IT,NAME|eq|Florence'
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)

        # check SuggestFilterBackend
        # --------------------------
        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression('"NAME" ILIKE \'%flo%\'')
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'suggest': 'NAME|flo'
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)

        # check SuggestFilterBackend + FieldFilterBackend
        # -----------------------------------------------
        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression(
            '"NAME" ILIKE \'%flo%\' AND "ISO2_CODE" = \'IT\'')
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'suggest': 'NAME|flo',
                'field': 'ISO2_CODE|eq|IT'
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)
        self.assertEqual(resp['vector']['count'], 2)

        qgs_request = QgsFeatureRequest()
        qgs_request.setFilterExpression(
            '"NAME" ILIKE \'%flo%\' AND "ISO2_CODE" = \'IT\' AND "NAME" = \'Florence\''
        )
        total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

        resp = json.loads(
            self._testApiCall('core-vector-api', [
                'data', 'qdjango', self.project310.instance.pk,
                cities.qgs_layer_id
            ], {
                'suggest': 'NAME|flo',
                'field': 'ISO2_CODE|eq|IT,NAME|eq|Florence'
            }).content)

        self.assertEqual(resp['vector']['count'], total_count)
        self.assertEqual(resp['vector']['count'], 1)
Ejemplo n.º 8
0
    def _get_relations(self,
                       with_relations=[],
                       flayer=None,
                       ffactory=None,
                       request=None,
                       res={}):
        """
        Check for relations adn add to res
        :param with_relations: relations id list
        :param source_layer: QgsVectorLayer instance of father
        :param res: result dict to send into response
        """

        qgs_prj = get_qgs_project(flayer.project.qgis_file.path)

        relations = None
        for relation_id in with_relations:
            qgs_relation = qgs_prj.relationManager().relation(relation_id)
            if not qgs_relation.isValid():
                logger.error(f'Relation with id {relation_id} is not valid.')
                continue

            csource_layer = qgs_relation.referencingLayer()
            clayer = flayer.project.layer_set.get(
                qgs_layer_id=csource_layer.id())

            # get every qplotly active for child layer
            qplotlies = clayer.qplotlywidget_set.all()
            if len(qplotlies) == 0:
                continue

            if not relations:
                relations = {relation_id: []}
            else:
                relations.update({relation_id: []})

            for qplotly in qplotlies:
                settings = QplotlySettings()
                if not settings.read_from_model(qplotly):
                    logger.error(
                        f'Error on load qlotly settings for layer pk {clayer.pk}.'
                    )
                    continue

                factory = QplotlyFactoringRelation(settings,
                                                   request=request,
                                                   layer=clayer)
                factory.source_layer = csource_layer

                # create expression
                ffiltered_features = ffactory.source_layer.getFeatures(
                    ffactory.qgsrequest)
                factory.set_father_features_expresion(
                    qgs_relation=qgs_relation,
                    ffiltered_features=ffiltered_features)

                factory.rebuild()

                relations[relation_id].append({
                    'id': qplotly.pk,
                    'data': factory.trace
                })

            if 'relations' not in res and relations:
                res.update({'relations': relations})