def get_pdf(self, params: Dict[str, str], response: QgsServerResponse) -> None: """ Get PDF files previously exported """ ptoken = params.get('TOKEN') if not ptoken: raise CadastreError(400, "Missing parameter: token") path = self.cachedir / ('%s.pdf' % ptoken) if self.debugMode: QgsMessageLog.logMessage("GetPDF = path is %s" % path.as_posix(), 'cadastre', Qgis.Debug) if not path.exists(): raise CadastreError(404, "PDF not found") # Send PDF response.setHeader('Content-type', 'application/pdf') response.setStatusCode(200) try: response.write(path.read_bytes()) path.unlink() except: QgsMessageLog.logMessage("Error occured while reading PDF file", 'cadastre', Qgis.Critical) raise
def write_json_response(data: Dict[str, str], response: QgsServerResponse, code: int = 200) -> None: """ Write data as json response """ response.setStatusCode(code) response.setHeader("Content-Type", "application/json") response.write(json.dumps(data))
def get_pdf(self, params: Dict[str,str], response: QgsServerResponse ) -> None: """ Get PDF files previously exported """ ptoken = params.get('TOKEN') if not ptoken: raise CadastreError(400,"Missing parameter: token") path = self.cachedir / ('%s.pdf' % ptoken) if self.debugMode: QgsMessageLog.logMessage("GetPDF = path is %s" % path.as_posix(),'cadastre', Qgis.Debug) if not path.exists(): raise CadastreError(404,"PDF not found") # Send PDF response.setHeader('Content-type', 'application/pdf') response.setStatusCode(200) try: response.write(path.read_bytes()) path.unlink() except: QgsMessageLog.logMessage("Error occured while reading PDF file",'cadastre',QGis.Critical) raise
def virtualFields(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get virtual fields for features In parameters: LAYER=wms-layer-name VIRTUALS={"key1": "first expression", "key2": "second expression"} // optionals FILTER=An expression to filter layer FIELDS=list of requested field separated by comma WITH_GEOMETRY=False """ layer_name = params.get('LAYER', '') if not layer_name: raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = find_vector_layer(layer_name, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'VirtualFields': {} provided".format(layer_name), 400) # get virtuals virtuals = params.get('VIRTUALS', '') if not virtuals: raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS parameter is mandatory", 400) # try to load virtuals dict try: vir_json = json.loads(virtuals) except Exception: QgsMessageLog.logMessage( "JSON loads virtuals '{}' exception:\n{}".format(virtuals, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS '{}' are not well formed".format(virtuals), 400) if not isinstance(vir_json, dict): raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS '{}' are not well formed".format(virtuals), 400) # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # parse virtuals exp_map = {} exp_parser_errors = [] for k, e in vir_json.items(): exp = QgsExpression(e) exp.setGeomCalculator(da) exp.setDistanceUnits(project.distanceUnits()) exp.setAreaUnits(project.areaUnits()) if exp.hasParserError(): exp_parser_errors.append('Error "{}": {}'.format(e, exp.parserErrorString())) continue if not exp.isValid(): exp_parser_errors.append('Expression not valid "{}"'.format(e)) continue exp.prepare(exp_context) exp_map[k] = exp # expression parser errors found if exp_parser_errors: raise ExpressionServiceError( "Bad request error", "Invalid VIRTUALS for 'VirtualFields':\n{}".format('\n'.join(exp_parser_errors)), 400) req = QgsFeatureRequest() # get filter req_filter = params.get('FILTER', '') if req_filter: req_exp = QgsExpression(req_filter) req_exp.setGeomCalculator(da) req_exp.setDistanceUnits(project.distanceUnits()) req_exp.setAreaUnits(project.areaUnits()) if req_exp.hasParserError(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'VirtualFields' Error \"{}\": {}".format( req_filter, req_exp.parserErrorString()), 400) if not req_exp.isValid(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'VirtualFields' Expression not valid \"{}\"".format(req_filter), 400) req_exp.prepare(exp_context) req = QgsFeatureRequest(req_exp, exp_context) # With geometry with_geom = params.get('WITH_GEOMETRY', '').lower() in ['true', '1', 't'] if not with_geom: req.setFlags(QgsFeatureRequest.NoGeometry) # Fields pk_attributes = layer.primaryKeyAttributes() attribute_list = [i for i in pk_attributes] fields = layer.fields() r_fields = [f.strip() for f in params.get('FIELDS', '').split(',') if f] for f in r_fields: attribute_list.append(fields.indexOf(f)) # response response.setStatusCode(200) response.setHeader("Content-Type", "application/json") response.write('{ "type": "FeatureCollection","features":[') response.flush() json_exporter = QgsJsonExporter(layer) if attribute_list: json_exporter.setAttributes(attribute_list) separator = '' for feat in layer.getFeatures(req): fid = layer_name + '.' + get_server_fid(feat, pk_attributes) extra = {} # Update context exp_context.setFeature(feat) exp_context.setFields(feat.fields()) # Evaluate expressions for virtual fields errors = {} for k, exp in exp_map.items(): value = exp.evaluate(exp_context) if exp.hasEvalError(): extra[k] = None errors[k] = exp.evalErrorString() else: extra[k] = json.loads(QgsJsonUtils.encodeValue(value)) errors[k] = exp.expression() response.write(separator + json_exporter.exportFeature(feat, extra, fid)) response.flush() separator = ',\n' response.write(']}') return
def get_feature_with_form_scope(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get filtered features with a form scope In parameters: LAYER=wms-layer-name FILTER=An expression to filter layer FORM_FEATURE={"type": "Feature", "geometry": {}, "properties": {}} // optionals FIELDS=list of requested field separated by comma WITH_GEOMETRY=False """ layer_name = params.get('LAYER', '') if not layer_name: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = find_vector_layer(layer_name, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'VirtualField': {} provided".format(layer_name), 400) # get filter exp_filter = params.get('FILTER', '') if not exp_filter: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FILTER parameter is mandatory", 400) # get form feature form_feature = params.get('FORM_FEATURE', '') if not form_feature: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE parameter is mandatory", 400) # Check features try: geojson = json.loads(form_feature) except Exception: QgsMessageLog.logMessage( "JSON loads form feature '{}' exception:\n{}".format(form_feature, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed".format(form_feature), 400) if not geojson or not isinstance(geojson, dict): raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed".format(form_feature), 400) if ('type' not in geojson) or geojson['type'] != 'Feature': raise ExpressionServiceError( "Bad request error", ("Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed: type not defined " "or not Feature.").format(form_feature), 400) # try to load form feature # read fields form_feature_fields = QgsJsonUtils.stringToFields( form_feature, QTextCodec.codecForName("UTF-8")) # read features form_feature_list = QgsJsonUtils.stringToFeatureList( form_feature, form_feature_fields, QTextCodec.codecForName("UTF-8")) # features not well formed if not form_feature_list: raise ExpressionServiceError( "Bad request error", ("Invalid FORM_FEATURE for 'GetFeatureWithFormScope': not GeoJSON feature provided\n" "{}").format(form_feature), 400) if len(form_feature_list) != 1: raise ExpressionServiceError( "Bad request error", ("Invalid FORM_FEATURE for 'GetFeatureWithFormScope': not GeoJSON feature provided\n" "{}").format(form_feature), 400) # Get the form feature form_feat = form_feature_list[0] # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) exp_context.appendScope(QgsExpressionContextUtils.formScope(form_feat)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # Get filter expression exp_f = QgsExpression(exp_filter) exp_f.setGeomCalculator(da) exp_f.setDistanceUnits(project.distanceUnits()) exp_f.setAreaUnits(project.areaUnits()) if exp_f.hasParserError(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'GetFeatureWithFormScope': Error \"{}\": {}".format( exp_filter, exp_f.parserErrorString()), 400) if not exp_f.isValid(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'GetFeatureWithFormScope': Expression not valid \"{}\"".format(exp_filter), 400) exp_f.prepare(exp_context) req = QgsFeatureRequest(exp_f, exp_context) # With geometry with_geom = params.get('WITH_GEOMETRY', '').lower() in ['true', '1', 't'] if not with_geom: req.setFlags(QgsFeatureRequest.NoGeometry) # Fields pk_attributes = layer.primaryKeyAttributes() attribute_list = [i for i in pk_attributes] fields = layer.fields() r_fields = [f.strip() for f in params.get('FIELDS', '').split(',') if f] for f in r_fields: attribute_list.append(fields.indexOf(f)) # response response.setStatusCode(200) response.setHeader("Content-Type", "application/json") response.write('{ "type": "FeatureCollection","features":[') response.flush() json_exporter = QgsJsonExporter(layer) if attribute_list: json_exporter.setAttributes(attribute_list) separator = '' for feat in layer.getFeatures(req): fid = layer_name + '.' + get_server_fid(feat, pk_attributes) response.write(separator + json_exporter.exportFeature(feat, {}, fid)) response.flush() separator = ',\n' response.write(']}') return
def get_print(self, params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get print document """ template = params.get('TEMPLATE') feature_filter = params.get('EXP_FILTER', None) scale = params.get('SCALE') scales = params.get('SCALES') try: if not template: raise AtlasPrintException('TEMPLATE is required') if feature_filter: expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( 'Expression is invalid: {}'.format( expression.parserErrorString())) if scale and scales: raise AtlasPrintException( 'SCALE and SCALES can not be used together.') if scale: try: scale = int(scale) except ValueError: raise AtlasPrintException('Invalid number in SCALE.') if scales: try: scales = [int(scale) for scale in scales.split(',')] except ValueError: raise AtlasPrintException('Invalid number in SCALES.') additional_params = { k: v for k, v in params.items() if k not in ['TEMPLATE', 'EXP_FILTER', 'SCALE', 'SCALES'] } pdf_path = print_layout(project=project, layout_name=params['TEMPLATE'], scale=scale, scales=scales, feature_filter=feature_filter, **additional_params) except AtlasPrintException as e: raise AtlasPrintError( 400, 'ATLAS - Error from the user while generating the PDF: {}'. format(e)) except Exception: self.logger.critical("Unhandled exception:\n{}".format( traceback.format_exc())) raise AtlasPrintError(500, "Internal 'atlasprint' service error") path = Path(pdf_path) if not path.exists(): raise AtlasPrintError(404, "ATLAS PDF not found") # Send PDF response.setHeader('Content-Type', 'application/pdf') response.setStatusCode(200) try: response.write(path.read_bytes()) path.unlink() except Exception: self.logger.critical("Error occured while reading PDF file") raise
def get_print( self, params: Dict[str, str], response: QgsServerResponse, project: QgsProject ) -> None: """ Get print document """ template = params.get("TEMPLATE") feature_filter = params.get("EXP_FILTER", None) scale = params.get("SCALE") scales = params.get("SCALES") output_format = parse_output_format(params.get("FORMAT", params.get("format"))) try: if not template: raise AtlasPrintException("TEMPLATE is required") if feature_filter: expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( "Expression is invalid: {}".format( expression.parserErrorString() ) ) if scale and scales: raise AtlasPrintException("SCALE and SCALES can not be used together.") if scale: try: scale = int(scale) except ValueError: raise AtlasPrintException("Invalid number in SCALE.") if scales: try: scales = [int(scale) for scale in scales.split(",")] except ValueError: raise AtlasPrintException("Invalid number in SCALES.") additional_params = { k: v for k, v in params.items() if k not in ( "TEMPLATE", "EXP_FILTER", "SCALE", "SCALES", "FORMAT", "MAP", "REQUEST", "SERVICE", ) } Logger().info( "Additional params: " + str(additional_params["PERMIT_REQUEST_ID"]) ) # When the project has OAPIF datasources, the sources must first be reloaded. # In order to prevent massive request to DB, a basic server side filter is added OAPIFRefresher.refresh_geocity_oapif_layers_for_current_atlas_feature( additional_params["PERMIT_REQUEST_ID"] ) Logger().info("Refreshed: " + str(additional_params["PERMIT_REQUEST_ID"])) output_path = print_layout( project=project, layout_name=params["TEMPLATE"], output_format=output_format, scale=scale, scales=scales, feature_filter=feature_filter, **additional_params, ) except AtlasPrintException as e: raise AtlasPrintError( 400, "ATLAS - Error from the user while generating the PDF: {}".format(e), ) except Exception: self.logger.critical( "Unhandled exception:\n{}".format(traceback.format_exc()) ) raise AtlasPrintError(500, "Internal 'atlasprint' service error") path = Path(output_path) if not path.exists(): raise AtlasPrintError(404, "ATLAS {} not found".format(output_format.name)) # Send PDF response.setHeader("Content-Type", output_format.value) response.setStatusCode(200) try: response.write(path.read_bytes()) path.unlink() except Exception: self.logger.critical( "Error occurred while reading {} file".format(output_format.name) ) raise
def write_json_response( data: Dict[str,str], response: QgsServerResponse, code: int=200) -> None: """ Write data as json response """ response.setStatusCode(code) response.setHeader("Content-Type", "application/json") response.write(json.dumps(data))