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)
def get(self, request, **kwargs): qplotly = QplotlyWidget.objects.get(pk=kwargs['pk']) # load settings from db settings = QplotlySettings() if not settings.read_from_model(qplotly): #todo: raise a API exception raise Exception() # get bbox if is sent rect = None if 'bbox' in kwargs: rect = QgsReferencedRectangle( QgsRectangle(**kwargs['bbox']), QgsCoordinateReferenceSystem(qplotly.project.group.srid.srid)) # instace q QplotlyFactory factory = QplotlyFactoring(settings, visible_region=rect) # is possibile get the first layer factory.source_layer = get_qgis_layer( qplotly.layers.get(qgs_layer_id=settings.source_layer_id, project_id=kwargs['project_id'])) factory.rebuild() res = {'data': factory.trace} self.results.results.update(res) return Response(self.results.results)
def testGetQgisFeaturesAttributeFilters(self): """Test QGIS API attribute filters""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) features = get_qgis_features(qgis_layer, attribute_filters={'name': 'a point'}) self.assertEqual(len(features), 1) self.assertTrue(features[0].id(), 1) features = get_qgis_features( qgis_layer, attribute_filters={'name': 'another point'}) self.assertEqual(len(features), 1) self.assertTrue(features[0].id(), 2) features = get_qgis_features(qgis_layer, attribute_filters={ 'name': 'another point', 'pkuid': 2 }) self.assertEqual(len(features), 1) self.assertTrue(features[0].id(), 2) features = get_qgis_features(qgis_layer, attribute_filters={ 'name': 'another point', 'pkuid': 9999 }) self.assertEqual(len(features), 0) features = get_qgis_features( qgis_layer, attribute_filters={'name': 'not_existent'}) self.assertEqual(len(features), 0)
def get_constraint_geometry(self): """Returns the geometry from the constraint layer and rule :return: the constraint geometry and the number of matched records :rtype: tuple( MultiPolygon, integer) """ constraint_layer = get_qgis_layer(self.constraint.constraint_layer) layer = get_qgis_layer(self.constraint.layer) # Get the geometries from constraint layer and rule qgis_feature_request = QgsFeatureRequest() qgis_feature_request.setFilterExpression(self.rule) features = get_qgis_features(constraint_layer, qgis_feature_request, exclude_fields='__all__') if not features: return '', 0 geometry = QgsMultiPolygon() for feature in features: geom = feature.geometry() if geom.isMultipart(): geom = [g for g in geom.constGet()] else: geom = [geom.constGet()] i = 0 for g in geom: geometry.insertGeometry(g.clone(), 0) i += 1 # Now, transform into a GEOS geometry if constraint_layer.crs() != layer.crs(): ct = QgsCoordinateTransform( QgsCoordinateReferenceSystem(constraint_layer.crs()), QgsCoordinateReferenceSystem(layer.crs()), QgsCoordinateTransformContext()) geometry.transform(ct) constraint_geometry = MultiPolygon.from_ewkt( 'SRID=%s;' % layer.crs().postgisSrid() + geometry.asWkt()) return constraint_geometry, constraint_geometry.num_geom
def get(self, request, **kwargs): qplotly = QplotlyWidget.objects.get(pk=kwargs['pk']) # load settings from db settings = QplotlySettings() if not settings.read_from_model(qplotly): raise Exception() # patch for xml setting linked to layer with same datasource. qgs_layer_id = kwargs[ 'qgs_layer_id'] if 'qgs_layer_id' in kwargs else settings.source_layer_id # get bbox if is sent # 2021/01/12 using IntersectBBOXFilter rect = None #if 'bbox' in kwargs: # rect = QgsReferencedRectangle(QgsRectangle(**kwargs['bbox']), # QgsCoordinateReferenceSystem(qplotly.project.group.srid.srid)) # instance a QplotlyFactory layer = Layer.objects.get(qgs_layer_id=qgs_layer_id, project_id=kwargs['project_id']) factory = QplotlyFactoring(settings, visible_region=rect, request=request, layer=layer) # is possible get the first layer factory.source_layer = get_qgis_layer( qplotly.layers.get(qgs_layer_id=settings.source_layer_id, project_id=kwargs['project_id'])) factory.rebuild() res = {'data': factory.trace} # if withrelations was sent add relations trace values # ---------------------------------------------------- if request.method == 'POST': request_data = request.data else: request_data = request.query_params with_relations = request_data.get(WITH_RELATIONS_PARAM) if with_relations: self._get_relations( with_relations=with_relations.split(','), flayer=layer, ffactory=factory, request=request, res=res, ) self.results.results.update(res) return Response(self.results.results)
def set_metadata_relations(self, request, **kwargs): # init relations self.set_relations() # Determine if we are using an old and bugged version of QGIS IS_QGIS_3_10 = Qgis.QGIS_VERSION.startswith('3.10') for idr, relation in list(self.relations.items()): # check if in relation there is referencedLayer == self layer if relation['referencedLayer'] == self.layer.qgs_layer_id: # get relation layer object relation_layer = self._layer_model.objects.get( qgs_layer_id=relation['referencingLayer'], project=self.layer.project) # qgis_layer is the referenced layer qgis_layer = self.layer.qgis_layer referenced_field_is_pk = [ qgis_layer.fields().indexFromName( relation['fieldRef']['referencedField']) ] == qgis_layer.primaryKeyAttributes() # It's an old and buggy QGIS version so we cannot trust primaryKeyAttributes() and we go guessing if IS_QGIS_3_10: field_index = qgis_layer.fields().indexFromName( relation['fieldRef']['referencedField']) # Safety check if field_index >= 0: field = qgis_layer.fields()[field_index] default_clause = qgis_layer.dataProvider( ).defaultValueClause(field_index) constraints = qgis_layer.fieldConstraints(field_index) not_null = bool(constraints & QgsFieldConstraints.ConstraintNotNull) and \ field.constraints().constraintStrength( QgsFieldConstraints.ConstraintNotNull) == QgsFieldConstraints.ConstraintStrengthHard unique = bool(constraints & QgsFieldConstraints.ConstraintUnique) and \ field.constraints().constraintStrength( QgsFieldConstraints.ConstraintUnique) == QgsFieldConstraints.ConstraintStrengthHard referenced_field_is_pk = unique and default_clause and not_null self.metadata_relations[ relation['referencingLayer']] = MetadataVectorLayer( get_qgis_layer(relation_layer), relation_layer.origname, idr, layer=relation_layer, referencing_field=relation['fieldRef'] ['referencingField'], layer_id=relation_layer.pk, referenced_field_is_pk=referenced_field_is_pk)
def layer_is_empty(self, layer): """ Check if a vector layer is empty (not data) :param layer: qdjango Layer model instance :return: True or False :rtype: boolean """ qgis_layer = get_qgis_layer(layer) if qgis_layer.type() == QgsMapLayer.VectorLayer: return not bool(count_qgis_features(qgis_layer)) else: return False
def testGetQgisFeaturesExcludeFields(self): """Test QGIS API get_qgis_features with exclude fields filter""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) features = get_qgis_features(qgis_layer, exclude_fields=['pkuid']) self.assertEqual(len(features), 2) self.assertIsNone(features[0].attribute('pkuid')) self.assertIsNotNone(features[0].attribute('name')) features = get_qgis_features(qgis_layer, exclude_fields=['name']) self.assertEqual(len(features), 2) self.assertIsNotNone(features[0].attribute('pkuid')) self.assertIsNone(features[0].attribute('name'))
def testGetQgisFeaturesAll(self): """Test QGIS API get_qgis_features with all features""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) # Test get all features features = get_qgis_features(qgis_layer) self.assertEqual(len(features), qgis_layer.featureCount()) # Check has geometry self.assertFalse(features[0].geometry().isNull()) # Get all features, no geometry features = get_qgis_features(qgis_layer, with_geometry=False) self.assertEqual(len(features), qgis_layer.featureCount()) # Check has geometry self.assertTrue(features[0].geometry().isNull())
def set_metadata_layer(self, request, **kwargs): """Set the metadata layer to a QgsVectorLayer instance returns a dictionary with layer information and the QGIS layer instance """ self.layer = self.get_layer_by_params(kwargs) # set layer_name self.layer_name = self.layer.origname qgis_layer = get_qgis_layer(self.layer) # create model and add to editing_layers self.metadata_layer = MetadataVectorLayer(qgis_layer, self.layer.origname, layer_id=self.layer.pk)
def testGetQgisFeaturesBbox(self): """Test QGIS API get_qgis_features with BBOX filter""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) features = get_qgis_features(qgis_layer, bbox_filter=qgis_layer.extent()) self.assertEqual(len(features), 2) bbox = QgsRectangle(qgis_layer.extent().xMinimum(), qgis_layer.extent().yMinimum(), qgis_layer.extent().xMinimum() + 1, qgis_layer.extent().yMinimum() + 1) features = get_qgis_features(qgis_layer, bbox_filter=bbox) self.assertEqual(len(features), 1)
def get(self, request, project_id, qgs_layer_id, **kwargs): try: layer = Layer.objects.get(project_id=project_id, qgs_layer_id=qgs_layer_id) rts = RTS(get_qgis_layer(layer)) # Check if is valid if not rts.isValid(): self.results.result = False self.results.error = f'{qgs_layer_id} is not a instance of QgsRasterLayer' return Response(self.results.results) # Check if layer raster time series is activated if not QRasterTimeSeriesLayer.is_activated(layer): self.results.result = False self.results.error = f'{qgs_layer_id} is not activated for time series' return Response(self.results.results) # translate Qdate to python date pydate = [] for d in rts.dates(): pydate.append(d.toPyDate()) self.results.results.update({ 'dates': pydate, 'names': rts.bands(), 'wavelength': rts.wavelength(), 'numberofbands': rts.numberOfBands(), 'numberofobservations': rts.numberOfObservations() }) except Exception as e: logger.error(f'[QRTSeries] {e}') self.results.result = False self.results.error = str(e) return Response(self.results.results)
def testGetQgisFeaturesSearch(self): """Test QGIS API get_qgis_features with search filter""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) features = get_qgis_features(qgis_layer, search_filter='1') self.assertEqual(len(features), 1) self.assertTrue(features[0].id(), 1) features = get_qgis_features(qgis_layer, search_filter='another') self.assertEqual(len(features), 1) self.assertTrue(features[0].id(), 2) features = get_qgis_features(qgis_layer, search_filter='point') self.assertEqual(len(features), 2) # not existent features = get_qgis_features(qgis_layer, search_filter='not_exists') self.assertEqual(len(features), 0)
def testGetQgisFeaturesCombinedFilters(self): """Test QGIS API attribute combined filters""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) features = get_qgis_features(qgis_layer, attribute_filters={ 'name': 'a point' }, search_filter='not_existent') self.assertEqual(len(features), 0) features = get_qgis_features(qgis_layer, attribute_filters={ 'name': 'another point' }, search_filter='1') self.assertEqual(len(features), 0) features = get_qgis_features(qgis_layer, attribute_filters={ 'name': 'another point' }, search_filter='2') self.assertEqual(len(features), 1) self.assertTrue(features[0].id(), 2)
def testGetQgisFeaturesExtraSubsetString(self): """Test QGIS API get_qgis_features with subset string filter""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) features = get_qgis_features(qgis_layer) self.assertEqual(len(features), 2) features = get_qgis_features( qgis_layer, extra_subset_string='name != \'another point\'') self.assertEqual(len(features), 1) self.assertEqual(features[0]['name'], 'a point') # Check if restored features = get_qgis_features(qgis_layer) self.assertEqual(len(features), 2) features = get_qgis_features( qgis_layer, extra_subset_string='name == \'another point\'') self.assertEqual(len(features), 1) self.assertEqual(features[0]['name'], 'another point') # Check if original subset string is ANDed qgis_layer_clone = qgis_layer.clone() qgis_layer_clone.setSubsetString('name == \'another point\'') features = get_qgis_features(qgis_layer_clone) self.assertEqual(len(features), 1) self.assertEqual(features[0]['name'], 'another point') features = get_qgis_features( qgis_layer_clone, extra_subset_string='name != \'another point\'') self.assertEqual(len(features), 0) # Check if restored qgis_layer_clone.setSubsetString('name == \'another point\'') features = get_qgis_features(qgis_layer_clone) self.assertEqual(len(features), 1) self.assertEqual(features[0]['name'], 'another point')
def form_valid(self, form): if form.cleaned_data['active']: if not self.activated: self.activated = QRasterTimeSeriesLayer.objects.create(layer=self.layer) else: self.activated.save() # Add start date and end date rts = RTS(get_qgis_layer(self.layer)) dates = rts.dates() start_date = dates[0].toPyDate() end_date = dates[-1].toPyDate() self.activated.start_date = start_date self.activated.end_date = end_date self.activated.save() else: if self.activated: self.activated.delete() return super().form_valid(form)
def testGetQgisFeaturesPagination(self): """Test QGIS API get_qgis_features with pagination""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) # Test get first page features = get_qgis_features(qgis_layer, page=1, page_size=1) self.assertEqual(len(features), 1) self.assertTrue(features[0].id(), 1) # second page features = get_qgis_features(qgis_layer, page=1, page_size=1) self.assertEqual(len(features), 1) self.assertTrue(features[0].id(), 2) # out of range offset features = get_qgis_features(qgis_layer, page=100, page_size=1) self.assertEqual(len(features), 0) # out of range feature_count features = get_qgis_features(qgis_layer, page_size=1000) self.assertEqual(len(features), 2)
def set_metadata_layer(self, request, **kwargs): """Set the metadata layer to a QgsRasterLayer instance returns a dictionary with layer information and the QGIS layer instance """ self.layer = self._layer_model.objects.get(project_id=kwargs['project_id'], qgs_layer_id=kwargs['layer_name']) # set layer_name self.layer_name = self.layer.origname qgis_layer = get_qgis_layer(self.layer) # Only raster layer if qgis_layer.type() != QgsMapLayerType.RasterLayer: raise APIException(f"Layer with id {self.layer.qgs_layer_id}: is not a raster layer") # create model and add to editing_layers self.metadata_layer = MetadataRasterLayer( qgis_layer, self.layer.origname, layer_id=self.layer.pk )
def testGetQgisFeaturesOrdering(self): """Test QGIS API get_qgis_features with ordering""" qgis_layer = get_qgis_layer(self.layer) self.assertTrue(qgis_layer.isValid()) # Test get first page features = get_qgis_features(qgis_layer, ordering='name') self.assertEqual(len(features), 2) self.assertTrue(features[0].id(), 1) # second page features = get_qgis_features(qgis_layer, ordering='name') self.assertEqual(len(features), 2) self.assertTrue(features[0].id(), 2) # Test get first page features = get_qgis_features(qgis_layer, ordering='-name') self.assertEqual(len(features), 2) self.assertTrue(features[0].id(), 2) # not existent field (ignored) features = get_qgis_features(qgis_layer, ordering='not_exists') self.assertEqual(len(features), 2)
def to_representation(self, instance): ret = super(WidgetSerializer, self).to_representation(instance) ret['type'] = instance.widget_type # get edittype edittypes = eval(self.layer.edittypes) if ret['type'] == 'search': body = json.loads(instance.body) ret['options'] = { 'queryurl': None, 'title': body['title'], 'results': body['results'], 'filter': [], 'dozoomtoextent': body['dozoomtoextent'], #'zoom': body['zoom'], } for field in body['fields']: # if widgettype is selectbox, get values if 'widgettype' in field and field['widgettype'] == 'selectbox': qgis_layer = get_qgis_layer(self.layer) uniques = qgis_layer.uniqueValues( qgis_layer.fields().indexOf(field['name'])) values = [] for u in uniques: try: values.append( json.loads(QgsJsonUtils.encodeValue(u))) except Exception as e: logger.error(f'Response vector widget unique: {e}') continue field['input']['type'] = 'selectfield' if 'dependance' not in field['input']['options']: # check if field has a widget edit type # todo: add 'ValueRelation' case if field['name'] in edittypes and \ edittypes[field['name']]['widgetv2type'] in ('ValueMap'): field['input']['options']['values'] = edittypes[ field['name']]['values'] else: field['input']['options']['values'] = values else: field['input']['options']['values'] = [] #For AutoccOmpleteBox imput type if 'widgettype' in field and field[ 'widgettype'] == 'autocompletebox': field['input']['type'] = 'autocompletefield' input = field['input'] input['options']['blanktext'] = field['blanktext'] ret['options']['filter'].append({ 'op': field['filterop'], 'attribute': field['name'], 'label': field['label'], 'input': input, 'logicop': field.get('logicop', 'AND').upper() }) else: ret['body'] = json.loads(instance.body) return ret
def _add_extrafields(self, request, filepath, filename): """ Add extra fields to layer properties if sbp parameters are in http query parameters. """ # check for fields data in GET OR POST if request.method == 'POST': request_data = request.data else: request_data = request.query_params if 'sbp_qgs_layer_id' in request_data and 'sbp_fid' in request_data: try: vlayer = QgsVectorLayer(filepath+'.shp', filename, "ogr") if not vlayer: raise Exception(f'Failed to load layer {filepath}') # Try to add the layer feature of SearchByPolygon widget sbp_layer = get_qgis_layer( self.layer.project.layer_set.filter(qgs_layer_id=request_data['sbp_qgs_layer_id'])[0]) sbp_feature = sbp_layer.getFeature( int(request_data['sbp_fid'])) original_attributes_count = len(vlayer.fields()) assert vlayer.startEditing() # Add prefix to field name to avoid repeated names # Use 'p' as polygon prefix = 'p_' for f in sbp_feature.fields(): f.setName(prefix + f.name()) vlayer.addAttribute(f) # Save attributes if not vlayer.commitChanges(): # OGR returns an error if fields were renamed (for example when they are too long) # ignore the error in that case if 'ERROR: field with index' in str(vlayer.commitErrors()): vlayer.commitChanges() else: err_msg = f'Commit error for layer {filepath}' # Check for commit errors errs = vlayer.commitErrors() if len(errs) > 0: errs_msg = ', '.join(errs) err_msg = err_msg + f': {errs_msg}' raise Exception(err_msg) # Now add new attribute values assert vlayer.startEditing() # Add values to new fields features = [f for f in vlayer.getFeatures()] for feature in features: added_fields = {} field_index = original_attributes_count for f in sbp_feature.fields(): added_fields.update( {field_index: sbp_feature[f.name()]}) field_index += 1 vlayer.changeAttributeValues(feature.id(), added_fields) # Commit new fields and exit from editing if not vlayer.commitChanges(): err_msg = f'Commit error for layer {filepath}' # Check for commit errors errs = vlayer.commitErrors() if len(errs) > 0: errs_msg = ', '.join(errs) err_msg = err_msg + f': {errs_msg}' except Exception as e: logger.error(e)