def query_features(lang, layers, query): features = [] max_features_pro_layer = int(10 / len(layers)) terms = query.split() terms1 = ' & '.join([term + ('' if term.isdigit() else ':*') for term in terms]) if lang == 'fr' or lang == 'it': bodsearch = BodLayerFr else: bodsearch = BodLayerDe c.baseUrl = '' c.lang = lang c.path_url = '' for layer in layers: bodlayer = Session.query(bodsearch).get(layer) for model in models_from_name(layer): if hasattr(model, '__queryable_attributes__'): ftsFilter = 'to_tsvector(\'english\',' + ' || \' \' || '.join(["coalesce(%s::text,'') " % s for s in model.__queryable_attributes__]) + ") @@ to_tsquery('english','%s')" % terms1 for feature in Session.query(model).filter(ftsFilter).limit(max_features_pro_layer).all(): feature.compute_attribute() feature.compute_template(layer, bodlayer) layername = _(layer) html = '<b>%s </b><br>%s' % (layername[0:35]+'...' if len(layername) > 35 else layername, feature.preview) feature.attributes['html'] = html feature.layer_id = layer features.append(feature) return features
def get_features(layer, ids): features = [] for model in models_from_name(layer): for fid in ids: if len(features) < MAX_FEATURES: try: feature = Session.query(model).get(fid) if feature: features.append(feature) except exc.SQLAlchemyError: pass else: break return features
def datenstand(self, layer_id, datenstand): """ if the value in bod.dataset.datenstand == TAG_DATENSTAND, return the most recent date of the data table, else return the regular value datenstand. """ if datenstand == self.TAG_DATENSTAND: try: for model in models_from_name(layer_id): modified = Session.query(func.max(model.bgdi_created)) return modified.first()[0].strftime("%Y%m%d") except: return datenstand else: return datenstand
def search(self): # optional paramater "extent" # Get current map extent or calculate a 'sensitive' default based on available information (scale !) extent = request.params.get('extent') if extent is not None: try: extent = map(float, extent.split(',')) except ValueError: abort(400, "Parameter 'extent' is invalid. Use extent=656430,254350,657930,25585 for instance.") else: resolution = 1 / ((1 / (c.scale > 0 or 1000.0)) * 39.3701 * 72) meters = 300 * resolution cx, cy = c.bbox[0:2] extent = (cx - meters, cy - meters, cx + meters, cy + meters) c.extent = Polygon(((extent[0], extent[1]), (extent[0], extent[3]), (extent[2], extent[3]), (extent[2], extent[1]), (extent[0], extent[1]))) c.baseUrl = request.params.get('baseUrl') or '' # Request features features = [] layerCounter = 0 for layer_name in c.layers: layerCounter = layerCounter + 1 for model in models_from_name(layer_name): geom_filter = model.bbox_filter(c.scale, c.bbox) if c.timestamps is not None: time_filter = model.time_filter(c.timestamps[layerCounter-1]) else: time_filter = None if geom_filter is not None: query = Session.query(model).filter(geom_filter) if time_filter is not None: query = query.filter(time_filter) bodlayer = Session.query(self.bodsearch).get(layer_name) for feature in query.limit(MAX_FEATURES).all(): properties = {} feature.compute_template(layer_name, bodlayer) if self.format == 'raw': feature.compute_attribute() properties = feature.attributes properties['html'] = feature.html properties['layer_id'] = feature.layer_id properties['preview'] = feature.preview if (self.no_geom or layer_name == 'ch.kantone.cadastralwebmap-farbe') and 'print' not in request.params: features.append(Feature(id=feature.id, bbox=feature.geometry.bounds, properties=properties)) else: features.append(feature) # Send features back if 'print' in request.params: c.features = features return render('/tooltips/_print.mako') else: output = simplejson.dumps(FeatureCollection(features), cls=MapFishEncoder) cb_name = request.params.get('cb') if cb_name is not None: response.headers['Content-Type'] = 'text/javascript' return str(cb_name) + '(' + output + ');' else: response.headers['Content-Type'] = 'application/json' return output
def index(self): # if a list of layers was provided the first layer in the # list will be taken layer = c.layers[0] features = [] urlContent = request.url.split("?") id = urlContent[0].split("/")[len(urlContent[0].split("/")) - 1] # extended infos if '.html' in id: id = id.strip('.html') ids = id.split(',') if len(ids) > 1: innerHtml = '' for model in models_from_name(layer): items_nb = len(ids) item_count = 0 for fid in ids: feature = Session.query(model).get(fid) bodlayer = Session.query(self.bodsearch).get(layer) if feature is not None: feature.compute_template(layer, bodlayer) feature.compute_attribute() c.html_type = 'extended' c.feature = feature item_count = item_count + 1 if items_nb == item_count: c.last = True else: c.last = False innerHtml = innerHtml + render(feature.__template__) else: abort(404, 'One of the id you provided is not valid') feature.html = innerHtml body_tooltip = render('/tooltips/extended_tooltips.mako') feature.html = body_tooltip.encode('utf8') else: c.last = True for model in models_from_name(layer): if len(features) < MAX_FEATURES: feature = Session.query(model).get(id) bodlayer = Session.query(self.bodsearch).get(layer) if feature is not None: properties = {} feature.compute_template(layer, bodlayer) feature.compute_attribute() properties = feature.attributes c.html_type = 'extended' feature.html = render(feature.__template__) body_tooltip = render('/tooltips/extended_tooltips.mako') feature.html = body_tooltip.encode('utf8') if (self.no_geom): features.append(Feature(id=feature.id, bbox=feature.geometry.bounds, properties=feature.attributes)) else: features.append(feature) response.headers['Content-Type'] = 'text/html' return feature.html else: abort(404, 'One of the id you provided is not valid') else: break response.headers['Content-Type'] = 'text/html' return feature.html # not extended info for model in models_from_name(layer): if len(features) < MAX_FEATURES: feature = Session.query(model).get(id) if feature: properties = {} if self.format =='html': bodlayer = Session.query(self.bodsearch).get(layer) feature.compute_template(layer, bodlayer) c.html_type = 'full' feature.html = render(feature.__template__) properties['html'] = feature.html else: feature.compute_attribute() properties = feature.attributes if (self.no_geom): features.append(Feature(id=feature.id, bbox=feature.geometry.bounds, properties=properties)) else: features.append(feature) else: break output = simplejson.dumps(FeatureCollection(features), cls=MapFishEncoder) cb_name = request.params.get('cb') if cb_name is not None: response.headers['Content-Type'] = 'text/javascript' return str(cb_name) + '(' + output + ');' else: response.headers['Content-Type'] = 'application/json' return output
def index(self, id=None): ##----------------------------------------Session----------------------------------------## # Define which view are taken into account if self.mode in ['all','legend','bodsearch','preview','mobile']: query = Session.query(self.BodLayer) # Global variable defined in the config files Geodata_staging = config['geodata_staging'].split(',') # Query only view_bod_wmts_getcapabilities_{lang} elif self.mode == 'wmts': query = Session.query(self.GetCap) self.BodLayer = self.GetCap # random variable so that no filter is applied Geodata_staging = ['geodata_staging'] else: abort(400, 'The parameter provided for mode is not valid') ##----------------------------------------Properties----------------------------------------## # Per default all the properties are returned properties = request.params.get('properties','all') if properties == 'all': # Create a list with all the properties properties = [] # Create a list with all the properties of the selected table(s) for key in self.map_properties.keys(): # Populate the list of the properties with all the available keys properties.append(key) else: properties = properties.split(',') # Check if the property exists for prop in properties: if prop not in self.map_properties.keys(): abort(400, 'The property(-ies) you provided is not valid') if not isinstance(properties,list): abort(400, 'An error occured while parsing the properties') ##----------------------------------------Project----------------------------------------## # Per default the project api is selected if self.mode == 'legend': project = ['all'] else: project = request.params.get('project','api') project = project.split(',') if not isinstance(project,list): abort(400, 'An error occured while parsing the projects') ##----------------------------------------Layer_id----------------------------------------## if id is None: # Per default all layers are taken into account layer_id = request.params.get('layer','all') layer_id = layer_id.split(',') if not isinstance(layer_id,list): abort(400, 'An error occured while parsing the layer Id(s)') else: layer_id = id layer_id = layer_id.split(',') if not isinstance(layer_id,list): abort(400, 'An error occured while parsing the layer Id(s)') ##----------------------------------------SecureWMTS----------------------------------------## # This parameter is only used in mode = wmts ##----------------------------------------QueryString----------------------------------------## # Per default no query string are applied query_string = request.params.get('query') ##----------------------------------------Filters----------------------------------------## # Filter by staging attribute # If one if these 3 layers are in the list do not filter by staging mode if 'ch.swisstopo.pixelkarte-farbe' in layer_id or 'ch.swisstopo.pixelkarte-grau' in layer_id or 'ch.swisstopo.tml3d-hintergrund-karte' in layer_id and self.mode == 'legend': pass elif self.mode in ['all','legend','bodsearch','preview','mobile']: if 'integration' in Geodata_staging: query = query.filter(or_(self.BodLayer.staging == 'integration', self.BodLayer.staging == 'prod')) elif 'prod' in Geodata_staging: query = query.filter(self.BodLayer.staging == 'prod') if self.mode in ['bodsearch']: query = query.filter(self.BodLayer.bodsearch == 'true') # Filter by layer_id if layer_id[0] != 'all': list_layers = [] for l_id in layer_id: list_layers.append(self.BodLayer.bod_layer_id == l_id) query = query.filter(or_(*list_layers)) # Filter by project if project[0] != 'all': list_projects = [] for proj in project: list_projects.append(self.BodLayer.projekte.ilike('%%%s%%' % proj)) query = query.filter(or_(*list_projects)) # Filter by query string if query_string is not None: columns = [] # Iterate on the properties we are intrested in for prop in properties: columns.append(column_from_name(prop, self.map_properties).ilike('%%%s%%' % query_string)) # Full text search query = query.filter(or_(*columns)) ##----------------------------------------ResultsPreparation----------------------------------------## if self.mode == 'bodsearch': if query_string is None: abort(400, 'Please provide a query parameter') # Order the results query = query.order_by(self.BodLayer.kurzbezeichnung).order_by(self.BodLayer.bezeichnung).order_by(self.BodLayer.geobasisdatensatz_name) results = [r.json(query_string) for r in query] elif self.mode == 'legend': c.host = request.params.get('h', '%s://api.geo.admin.ch' % c.scheme) c.full = True c.hilight = '' for r in query: c.layer = r c.legend = r # If value in bod.dataset.datenstand == bgdi_created, return the most recent date of the data table if c.legend.datenstand == 'bgdi_created': for model in models_from_name(c.layer.bod_layer_id): modified = Session.query(func.max(model.bgdi_created)) c.legend.datenstand = modified.first()[0].strftime("%Y%m%d") elif self.mode == 'mobile': results = [r.json(query_string) for r in query] elif self.mode == 'wmts': c.layers = query c.themes = Session.query(self.GetCapThemes).all() # Per default the parameter secure wmts is set to false c.is_swisstopowmts = False c.service_metadata = Session.query(self.ServiceMetadata).filter(self.ServiceMetadata.pk_map_name.like('%wmts-bgdi%')).first() request_uri = request.environ.get("REQUEST_URI", "") if request_uri.find("1.0.0"): # new bucket WMTS c.onlineressource = "%s://wmts.geo.admin.ch" % c.scheme else: c.onlineressource = "%s://api.geo.admin.ch/wmts" % c.scheme elif self.mode == 'all': results = [q.layers_results(properties) for q in query] elif self.mode == 'preview': result = [q.layers_results(['bod_layer_id']) for q in query] ##----------------------------------------Results----------------------------------------## cb_name = request.params.get('cb') print_legend = request.params.get('print', False) #self.format = request.params.get('format','json') if self.mode == 'bodsearch' or self.mode == 'mobile': if cb_name is not None: response.headers['Content-Type'] = 'text/javascript' results = simplejson.dumps({"results": results}) return str(cb_name) + '(' + results + ');' else: response.headers['Content-Type'] = 'application/json' return simplejson.dumps({'results': results}) elif self.mode == 'legend': # Query only one layer at a time in legend mode if len(layer_id) != 1 or layer_id[0] == 'all': abort(400, "Please provide only one layer at a time") if not hasattr(c, 'layer'): abort(400, "The parameters you provided didn't return any layer") if print_legend == "true": return render('/bod-details-print.mako') else: response.headers['Content-Type'] = 'text/javascript' results = simplejson.dumps(render('/bod-details.mako')) if cb_name is not None: return str(cb_name) + '(' + results + ');' else: return results elif self.mode == 'wmts': response.headers['Content-Type'] = 'text/xml' response.headers['Pragma'] = 'public' response.headers['Expires'] = '0' response.headers['Cache-Control'] = 'no-cache' response.charset = 'utf-8' return render('/WMTSCapabilities.mako') elif self.mode == 'all': if cb_name is not None: response.headers['Content-Type'] = 'text/javascript' results = simplejson.dumps({"results": results}) return str(cb_name) + '(' + results + ');' else: response.headers['Content-Type'] = 'application/json' return simplejson.dumps({'results': results}) elif self.mode == 'preview': c.layers = [] for object in result: for id,bodLayerId in object.iteritems(): if bodLayerId not in c.layers: c.layers.append(bodLayerId) response.headers['Content-Type'] = mimetypes.types_map['.html'] response.charset = 'utf8' map_width = request.params.get('width',250) c.map_width = map_width return render('/layersPreview.mako')