def test_get_qgs_project(self): """test get_qgs_project""" qgs_project = get_qgs_project(self.qdjango_project.qgis_file.path) self.assertTrue(isinstance(qgs_project, QgsProject)) qgs_project = self.qdjango_project.qgis_project self.assertTrue(isinstance(qgs_project, QgsProject))
def qgis_project(self): """Returns the QgsProject instance corresponding to this Project, or None in case of errors :return: the QgsProject instance :rtype: QgsProject or None """ from qdjango.apps import get_qgs_project return get_qgs_project(self.qgis_file.path)
def test_get_qgs_project_virtual_layer(self): """test get_qgs_project with virtual layers geopackage_join.qgs (issue with invalid layers and QgsProject.setInstance)""" qgs_project = get_qgs_project('{}{}{}'.format(CURRENT_PATH, TEST_BASE_PATH, 'geopackage_join.qgs')) self.assertTrue(isinstance(qgs_project, QgsProject)) for layer in list(qgs_project.mapLayers().values()): self.assertTrue(layer.isValid(), 'Layer %s is not valid!' % layer.id())
def testCoreVectorApiConfig(self): """Test core-vector-api config""" # Add a constraint expression to "name" field project = get_qgs_project( Layer.objects.get(qgs_layer_id='spatialite_points20190604101052075' ).project.qgis_file.path) layer = project.mapLayers()['spatialite_points20190604101052075'] layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintExpression, QgsFieldConstraints.ConstraintStrengthHard) layer.setConstraintExpression(1, '"name" != \'my name is no name\'') response = self._testApiCall( 'core-vector-api', ['config', 'qdjango', '1', 'spatialite_points20190604101052075']) resp = json.loads(response.content) self.assertIsNone(resp["vector"]["count"]) self.assertEqual(resp["vector"]["format"], "GeoJSON") self.assertEqual(resp["vector"]["fields"], [{ 'name': 'pkuid', 'type': 'bigint', 'label': 'pkuid', 'editable': False, 'validate': { 'required': True, 'unique': True }, 'pk': True, 'default': 'Autogenerate', 'input': { 'type': 'text', 'options': {} } }, { 'name': 'name', 'type': 'varchar', 'label': 'name', 'editable': True, 'validate': { 'expression': '"name" != \'my name is no name\'' }, 'pk': False, 'default': '', 'input': { 'type': 'text', 'options': {} } }]) self.assertEqual(resp["vector"]["geometrytype"], "Point") self.assertIsNone(resp["vector"]["data"]) self.assertTrue(resp["result"]) self.assertIsNone(resp["featurelocks"])
def get_capabilities4layer(qgs_maplayer=None, **kwargs): """ Return bitwise layer capabilities (by QGIS consts) values :param qgs_maplayer: QgsMapLayer instance :param **kwargs: optional params :return: int """ # get qgs_maplayer if not set if not qgs_maplayer: qgs_maplayer = get_qgs_project(kwargs['layer'].project.qgis_file.path).mapLayers()[kwargs['layer'].qgs_layer_id] capabilities = 0 if bool(qgs_maplayer.flags() & QgsMapLayer.Identifiable): capabilities |= settings.QUERYABLE if bool(qgs_maplayer.flags() & QgsMapLayer.Searchable): capabilities |= settings.FILTRABLE return capabilities
def get_qgis_layer(layer_info): """Returns a QGIS vector layer from a layer information record. The layer is normally not a clone but it is the live instance of the QgsProject it belongs to. If the project does not exist a new layer will be created. :param layer_info: layer record from g3w suite table :type layer_info: Layer :return: a (possibly invalid) QGIS vector layer :rtype: QgsVectorLayer """ try: project = get_qgs_project(layer_info.project.qgis_file.path) return project.mapLayers()[layer_info.qgs_layer_id] except: provider_name = layer_info.layer_type datasource = layer_info.datasource name = layer_info.name return QgsVectorLayer(datasource, name, provider_name)
def to_representation(self, instance): ret = super(ProjectSerializer, self).to_representation(instance) # add a QGSMapLayer instance qgs_project = get_qgs_project(instance.qgis_file.path) # set init and map extent ret['initextent'], ret['extent'] = self.get_map_extent(instance) ret['print'] = json.loads(clean_for_json( instance.layouts)) if instance.layouts else [] # add layers data, widgets # init proprties ret['layers'] = [] ret['search'] = [] ret['widget'] = [] ret['relations'] = [] ret['no_legend'] = [] layers = {l.qgs_layer_id: l for l in instance.layer_set.all()} # check fo title if hasattr(settings, 'G3W_CLIENT_SEARCH_TITLE'): ret['search_title'] = _(settings.G3W_CLIENT_SEARCH_TITLE) # for client map like multilayer meta_layer = QdjangoMetaLayer() to_remove_from_layerstree = [] def readLeaf(layer, container): if 'nodes' in layer: for node in layer['nodes']: readLeaf(node, layer['nodes']) else: layer_serialized = LayerSerializer(layers[layer['id']], qgs_project=qgs_project) layer_serialized_data = layer_serialized.data # alter layer serialized data from plugin # send layerseralized original and came back only key->value changed for signal_receiver, data in after_serialized_project_layer.send( layer_serialized, layer=layers[layer['id']]): update_serializer_data(layer_serialized_data, data) layer_serialized_data[ 'multilayer'] = meta_layer.getCurrentByLayer( layer_serialized_data) # check for vectorjoins and add to project relations if layer_serialized_data['vectorjoins']: ret['relations'] += self.get_map_layers_relations_from_vectorjoins( layer['id'], layer_serialized_data['vectorjoins'], layers) del (layer_serialized_data['vectorjoins']) ret['layers'].append(layer_serialized_data) # get widgects for layer widgets = layers[layer['id']].widget_set.all() for widget in widgets: widget_serializzer_data = WidgetSerializer( widget, layer=layers[layer['id']]).data if widget_serializzer_data['type'] == 'search': widget_serializzer_data['options']['layerid'] = layer[ 'id'] widget_serializzer_data['options'][ 'querylayerid'] = layer['id'] ret['search'].append(widget_serializzer_data) else: load_qdjango_widget_layer.send(self, layer=layer, ret=ret, widget=widget) # add exclude to legend if layers[layer['id']].exclude_from_legend: ret['no_legend'].append(layers[layer['id']].qgs_layer_id) for l in ret['layerstree']: readLeaf(l, ret['layerstree']) # remove layers from layerstree for to_remove in to_remove_from_layerstree: to_remove[0].remove(to_remove[1]) # add baselayer default ret['initbaselayer'] = instance.baselayer.id if instance.baselayer else None # add relations if exists if instance.relations: ret['relations'] += self.get_map_layers_relations(instance) # add project metadata ret['metadata'] = self.get_metadata(instance, qgs_project) # set client options/actions ret.update(self._set_options(instance)) # set ow method ret['ows_method'] = self._set_ows_method(instance) # add html_page_title ret['html_page_title'] = u'{} | {}'.format( getattr(settings, 'G3WSUITE_CUSTOM_TITLE', 'g3w - client'), instance.title_ur if instance.title_ur else instance.title) # set name by language if is set if instance.title_ur: ret['name'] = instance.title_ur # Set to macrogroup images if options use_logo is checked try: macrogroup = instance.group.macrogroups.get(use_logo_client=True) ret['thumbnail'] = macrogroup.logo_img.url except: pass ret['search_endpoint'] = settings.G3W_CLIENT_SEARCH_ENDPOINT return ret
def layerstree(self, request, **kwargs): try: # Retrieve project qdjando instance and qgsproject instance project = get_object_or_404(Project, pk=kwargs['project_id']) qgs_project = get_qgs_project(project.qgis_file.path) # Validation theme name theme_collections = qgs_project.mapThemeCollection() map_themes = theme_collections.mapThemes() theme_name = kwargs['theme_name'] if len(map_themes) == 0: raise Exception( f"Themes are not available for project {project.title}") if theme_name not in map_themes: raise Exception(f"Theme name '{theme_name}' is not available!") map_theme = theme_collections.mapThemeState(theme_name) # Get node group expanded anche checked node_group_expanded = map_theme.expandedGroupNodes() node_group_checked = map_theme.checkedGroupNodes() # Layers checked are layers into mapTheme layerRecords node_layerids_checked = [] for r in map_theme.layerRecords(): id = r.layer().id() if id not in node_layerids_checked: node_layerids_checked.append(id) def build_group_name_by_parents(node): parent = node.parent() if parent and parent.nodeType() == 0 and parent.name() != '': return build_group_name_by_parents( parent) + '/' + node.name() else: return node.name() def build_tree(layertreenode): toRetLayers = [] for node in layertreenode.children(): toRetLayer = {'name': node.name()} try: # try for layer node toRetLayer.update({ 'id': node.layerId(), 'visible': True if node.layerId() in node_layerids_checked else False }) except: # Try to build by parent deep_tree_name = build_group_name_by_parents(node) toRetLayer.update({ 'mutually-exclusive': node.isMutuallyExclusive(), 'nodes': build_tree(node), 'checked': True if deep_tree_name in node_group_checked else False, 'expanded': True if deep_tree_name in node_group_expanded else False }) toRetLayers.append(toRetLayer) return toRetLayers layers_tree = build_tree(qgs_project.layerTreeRoot()) self.results.results.update({'data': layers_tree}) except Http404 as e: self.results.error = f"Project with id {kwargs['project_id']} not found!" self.results.result = False except Exception as e: self.results.error = str(e) self.results.result = False return Response(self.results.results)
def response_commit_mode(self, request): """ Perform commit operation with data :param request: API request object :return: Vector params """ # get post data from request object # data = request.data # post_layer_data = data[self.layer_name] post_layer_data = request.data new_relations = dict() # Store references to all layers that have been made editable, # used to commit/rollback at the end of the loop and on errors editing_layers = [] # Get the layer qgis_layer = self.metadata_layer.qgis_layer # Get the project qgis_project = get_qgs_project( Layer.objects.get( pk=self.metadata_layer.layer_id).project.qgis_file.path) # Check if we have transaction groups activated # Performs all operations in the editing buffer if we have transactions has_transactions = qgis_project.transactionGroup( qgis_layer.providerType(), QgsDataSourceUri(qgis_layer.source()).connectionInfo()) is not None try: if has_transactions: # Start layer editing on main layer if not self.metadata_layer.qgis_layer.startEditing(): raise Exception( _('Layer %s is not editable!') % self.metadata_layer.qgis_layer.name()) editing_layers.append(self.metadata_layer.qgis_layer) ref_insert_ids, ref_lock_ids = self.save_vector_data( self.metadata_layer, post_layer_data, has_transactions) # get every relationsedits post_relations_data = dict() if self.relations_data_key in post_layer_data and bool( post_layer_data[self.relations_data_key]): post_relations_data = post_layer_data[self.relations_data_key] # save relations if post data exists for referencing_layer in self.metadata_relations.keys(): if referencing_layer in post_relations_data: post_relation_data = post_relations_data[referencing_layer] if has_transactions: # Editing on related layers has already started because # it's part of a transaction group editing_layers.append( self.metadata_relations[referencing_layer]. qgis_layer) # instance lock for relation self.metadata_relations[referencing_layer].lock = LayerLock( appName=self.app_name, layer=self.metadata_relations[referencing_layer].layer, user=request.user, sessionid=self.sessionid) insert_ids, lock_ids = self.save_vector_data( self.metadata_relations[referencing_layer], post_relation_data, has_transactions, referenced_layer_insert_ids=ref_insert_ids) new_relations[referencing_layer] = { 'new': insert_ids, 'new_lockids': lock_ids } if has_transactions: # Commit changes on all editable layers # The check is required because when committing the # "parent" layer in a transaction group all other layers are # committed as well. for ql in editing_layers: if ql.isEditable() and not ql.commitChanges(): raise Exception( _('Backend error saving layer %s: %s') % (ql.name(), ql.commitErrors())) except ValidationError as ve: if has_transactions: for ql in editing_layers: ql.rollBack() self.results.update({'result': False, 'errors': ve.detail}) except Exception as e: if has_transactions: for ql in editing_layers: ql.rollBack() self.results.update({'result': False, 'errors': str(e)}) try: self.results.update({ 'response': { 'new': ref_insert_ids, 'new_lockids': ref_lock_ids, 'new_relations': new_relations } }) except: pass
def to_representation(self, instance): logging.warning('Serializer') ret = super(ProjectSerializer, self).to_representation(instance) logging.warning('Before reading project') # add a QGSMapLayer instance qgs_project = get_qgs_project(instance.qgis_file.path) logging.warning('Got project: %s' % qgs_project.fileName()) # set init and map extent ret['initextent'], ret['extent'] = self.get_map_extent(instance) ret['print'] = json.loads(clean_for_json( instance.layouts)) if instance.layouts else [] # Get layer which request.user can view: if self.request: view_layer_ids = [l.qgs_layer_id for l in get_objects_for_user(self.request.user, 'qdjango.view_layer', Layer) \ | get_objects_for_user(get_anonymous_user(), 'qdjango.view_layer', Layer)] # add layers data, widgets # init properties if qgs_project.layerTreeRoot().hasCustomLayerOrder(): ret['layers'] = {} else: ret['layers'] = [] ret['search'] = [] ret['widget'] = [] ret['relations'] = [] layers = {l.qgs_layer_id: l for l in instance.layer_set.all()} # check fo title if hasattr(settings, 'G3W_CLIENT_SEARCH_TITLE'): ret['search_title'] = _(settings.G3W_CLIENT_SEARCH_TITLE) # for client map like multilayer meta_layer = QdjangoMetaLayer() to_remove_from_layerstree = [] def readLeaf(layer, container): if 'nodes' in layer: for node in layer['nodes']: readLeaf(node, layer['nodes']) else: # Check for empty vector layer if settings.G3W_CLIENT_NOT_SHOW_EMPTY_VECTORLAYER and self.layer_is_empty( layers[layer['id']]): return # Check if layer is visible for user if self.request and not layer['id'] in view_layer_ids: return try: layer_serialized = LayerSerializer(layers[layer['id']], qgs_project=qgs_project) except KeyError: logger.error('Layer %s is missing from QGIS project!' % layer['id']) return layer_serialized_data = layer_serialized.data # alter layer serialized data from plugin # send layerseralized original and came back only key->value changed for signal_receiver, data in after_serialized_project_layer.send( layer_serialized, layer=layers[layer['id']], request=self.request): update_serializer_data(layer_serialized_data, data) layer_serialized_data[ 'multilayer'] = meta_layer.getCurrentByLayer( layer_serialized_data) # check for vectorjoins and add to project relations if layer_serialized_data['vectorjoins']: ret['relations'] += self.get_map_layers_relations_from_vectorjoins( layer['id'], layer_serialized_data['vectorjoins'], layers) del (layer_serialized_data['vectorjoins']) if qgs_project.layerTreeRoot().hasCustomLayerOrder(): ret['layers'].update( {layer_serialized_data['id']: layer_serialized_data}) else: ret['layers'].append(layer_serialized_data) # get widgects for layer widgets = layers[layer['id']].widget_set.all() for widget in widgets: widget_serializzer_data = WidgetSerializer( widget, layer=layers[layer['id']]).data if widget_serializzer_data['type'] == 'search': widget_serializzer_data['options']['layerid'] = layer[ 'id'] widget_serializzer_data['options'][ 'querylayerid'] = layer['id'] ret['search'].append(widget_serializzer_data) else: load_qdjango_widget_layer.send(self, layer=layer, ret=ret, widget=widget) for l in ret['layerstree']: readLeaf(l, ret['layerstree']) # remove layers from layerstree for to_remove in to_remove_from_layerstree: to_remove[0].remove(to_remove[1]) # for custom order layer # ====================== if qgs_project.layerTreeRoot().hasCustomLayerOrder(): custom_layer_order_ids = [] new_order = [] meta_layer = QdjangoMetaLayer() for qgs_layer in qgs_project.layerTreeRoot().customLayerOrder(): if qgs_layer.id() in ret['layers']: custom_layer_order_ids.append(qgs_layer.id()) lsd = ret['layers'][qgs_layer.id()] lsd['multilayer'] = meta_layer.getCurrentByLayer(lsd) new_order.append(lsd) # get layers not in customLayerOrder to add an the end of return layers list to_add_to_end = set( ret['layers'].keys()) - set(custom_layer_order_ids) for qgs_layer_id in list(to_add_to_end): lsd = ret['layers'][qgs_layer_id] lsd['multilayer'] = meta_layer.getCurrentByLayer(lsd) new_order.append(lsd) ret['layers'] = new_order # add baselayer default ret['initbaselayer'] = instance.baselayer.id if instance.baselayer else None # add relations if exists if instance.relations: ret['relations'] += self.get_map_layers_relations(instance) # add project metadata ret['metadata'] = self.get_metadata(instance, qgs_project) # set client options/actions ret.update(self._set_options(instance)) # set ow method ret['ows_method'] = self._set_ows_method(instance) # add html_page_title ret['html_page_title'] = u'{} | {}'.format( getattr(settings, 'G3WSUITE_CUSTOM_TITLE', 'g3w - client'), instance.title_ur if instance.title_ur else instance.title) # set name by language if is set if instance.title_ur: ret['name'] = instance.title_ur # Set to macrogroup images if options use_logo is checked try: if instance.group.use_logo_client: ret['thumbnail'] = instance.group.header_logo_img.url else: macrogroup = instance.group.macrogroups.get( use_logo_client=True) ret['thumbnail'] = macrogroup.logo_img.url except: pass ret['search_endpoint'] = settings.G3W_CLIENT_SEARCH_ENDPOINT # reset tokenfilter by session self.reset_filtertoken() return ret
def testPagination(self): """Test pagination""" world = Layer.objects.get(name='world') qgis_project = get_qgs_project(world.project.qgis_file.path) qgis_layer = qgis_project.mapLayer(world.qgs_layer_id) response = self._testApiCall( 'core-vector-api', ['data', 'qdjango', '1', world.qgs_layer_id], { 'in_bbox': '10.60,44.34,10.70,44.36', }) resp = json.loads(response.content) self.assertEqual(resp['vector']['count'], 1) # There is one feature returned by the query self.assertEqual(len(resp['vector']['data']['features']), 1) # Now we get 36 countries: resp = json.loads( self._testApiCall('core-vector-api', ['data', 'qdjango', '1', world.qgs_layer_id], { 'in_bbox': '-5,-4,12,80', }).content) self.assertEqual(len(resp['vector']['data']['features']), 36) self.assertEqual(resp['vector']['count'], 36) # Start paging # We have 4 full pages plus one of four for page in range(1, 4): resp = json.loads( self._testApiCall( 'core-vector-api', ['data', 'qdjango', '1', world.qgs_layer_id], { 'in_bbox': '-5,-4,12,80', 'page': page, 'page_size': 8, 'ordering': 'ogc_fid', }).content) self.assertEqual(len(resp['vector']['data']['features']), 8) self.assertEqual(resp['vector']['count'], 36) resp = json.loads( self._testApiCall( 'core-vector-api', ['data', 'qdjango', '1', world.qgs_layer_id], { 'in_bbox': '-5,-4,12,80', 'page': 5, 'page_size': 8, 'ordering': 'ogc_fid', }).content) self.assertEqual(len(resp['vector']['data']['features']), 4) self.assertEqual(resp['vector']['count'], 36) # Or one single page of 36 elements and 0 next pages resp = json.loads( self._testApiCall( 'core-vector-api', ['data', 'qdjango', '1', world.qgs_layer_id], { 'in_bbox': '-5,-4,12,80', 'page': 1, 'page_size': 36, 'ordering': 'ogc_fid', }).content) self.assertEqual(len(resp['vector']['data']['features']), 36) self.assertEqual(resp['vector']['count'], 36) resp = json.loads( self._testApiCall( 'core-vector-api', ['data', 'qdjango', '1', world.qgs_layer_id], { 'in_bbox': '-5,-4,12,80', 'page': 2, 'page_size': 36, 'ordering': 'ogc_fid', }).content) self.assertEqual(len(resp['vector']['data']['features']), 0) self.assertEqual(resp['vector']['count'], 36)
def baseDoRequest(self, q): request = self.request # Uppercase REQUEST if 'REQUEST' in [k.upper() for k in q.keys()]: if request.method == 'GET': ows_request = q['REQUEST'].upper() else: if request.content_type == 'application/x-www-form-urlencoded': ows_request = request.POST['REQUEST'].upper() else: ows_request = request.POST['REQUEST'][0].upper() q['REQUEST'] = ows_request # FIXME: proxy or redirect in case of WMS/WFS/XYZ cascading? qgs_project = get_qgs_project(self.project.qgis_file.path) if qgs_project is None: raise Http404('The requested QGIS project could not be loaded!') data = None if request.method == 'GET': method = QgsBufferServerRequest.GetMethod elif request.method == 'POST': method = QgsBufferServerRequest.PostMethod data = request.body elif request.method == 'PUT': method = QgsBufferServerRequest.PutMethod data = request.body elif request.method == 'PATCH': method = QgsBufferServerRequest.PatchMethod data = request.body elif request.method == 'HEAD': method = QgsBufferServerRequest.HeadMethod elif request.method == 'DELETE': method = QgsBufferServerRequest.DeleteMethod else: logger.warning("Request method not supported: %s, assuming GET" % request.method) method = QgsBufferServerRequest.GetMethod headers = {} for header_key in request.headers.keys(): headers[header_key] = request.headers.get(header_key) uri = request.build_absolute_uri(request.path) + '?' + q.urlencode() logger.debug('Calling QGIS Server: %s' % uri) qgs_request = QgsBufferServerRequest(uri, method, headers, data) # Attach user and project to the server object to make them accessible by the # server access control plugins (constraints etc.) QGS_SERVER.user = request.user QGS_SERVER.project = self.project qgs_response = QgsBufferServerResponse() try: QGS_SERVER.handleRequest(qgs_request, qgs_response, qgs_project) except Exception as ex: return HttpResponseServerError( reason="Error handling server request: %s" % ex) response = HttpResponse(bytes(qgs_response.body())) response.status_code = qgs_response.statusCode() for key, value in qgs_response.headers().items(): response[key] = value return response
def baseDoRequest(self, q): request = self.request # Uppercase REQUEST if 'REQUEST' in [k.upper() for k in q.keys()]: if request.method == 'GET': ows_request = q['REQUEST'].upper() else: if request.content_type == 'application/x-www-form-urlencoded': ows_request = request.POST['REQUEST'].upper() else: ows_request = request.POST['REQUEST'][0].upper() q['REQUEST'] = ows_request # FIXME: proxy or redirect in case of WMS/WFS/XYZ cascading? qgs_project = get_qgs_project(self.project.qgis_file.path) if qgs_project is None: raise Http404('The requested QGIS project could not be loaded!') data = None if request.method == 'GET': method = QgsBufferServerRequest.GetMethod elif request.method == 'POST': method = QgsBufferServerRequest.PostMethod data = request.body elif request.method == 'PUT': method = QgsBufferServerRequest.PutMethod data = request.body elif request.method == 'PATCH': method = QgsBufferServerRequest.PatchMethod data = request.body elif request.method == 'HEAD': method = QgsBufferServerRequest.HeadMethod elif request.method == 'DELETE': method = QgsBufferServerRequest.DeleteMethod else: logger.warning( "Request method not supported: %s, assuming GET" % request.method) method = QgsBufferServerRequest.GetMethod headers = {} for header_key in request.headers.keys(): headers[header_key] = request.headers.get(header_key) uri = request.build_absolute_uri(request.path) + '?' + q.urlencode() logger.debug('Calling QGIS Server: %s' % uri) qgs_request = QgsBufferServerRequest(uri, method, headers, data) # Attach user and project to the server object to make them accessible by the # server access control plugins (constraints etc.) QGS_SERVER.djrequest = request QGS_SERVER.user = request.user QGS_SERVER.project = self.project # For GetPrint QGIS functions that rely on layers visibility, we need to check # the layers from LAYERS use_ids = QgsServerProjectUtils.wmsUseLayerIds(qgs_project) tree_root = qgs_project.layerTreeRoot() # Loop through the layers and make them visible for layer_name in qgs_request.queryParameter('LAYERS').split(','): layer_name = urllib.parse.unquote(layer_name) layer = None if use_ids: layer = qgs_project.mapLayer(layer_name) else: try: layer = qgs_project.mapLayersByName(layer_name)[0] except: # short name? for l in qgs_project.mapLayers().values(): if l.shortName() == layer_name: layer = l break if layer is None: logger.warning( 'Could not find layer "{}" when configuring OWS call'.format(layer_name)) else: layer_node = tree_root.findLayer(layer) if layer_node is not None: layer_node.setItemVisibilityCheckedParentRecursive(True) else: logger.warning( 'Could not find layer tree node "{}" when configuring OWS call'.format(layer_name)) qgs_response = QgsBufferServerResponse() try: QGS_SERVER.handleRequest(qgs_request, qgs_response, qgs_project) except Exception as ex: return HttpResponseServerError(reason="Error handling server request: %s" % ex) response = HttpResponse(bytes(qgs_response.body())) response.status_code = qgs_response.statusCode() for key, value in qgs_response.headers().items(): response[key] = value return response