def _identify(request): params = IdentifyServiceValidation(request) response = {'results': []} # Determine layer types # Grid layers are serverless layersDB = [] layersGrid = [] isScaleDependent = has_buffer(params.imageDisplay, params.mapExtent, params.tolerance) scale = get_scale(params.imageDisplay, params.mapExtent) if isScaleDependent else None if params.layers == 'all': model = get_bod_model(params.lang) query = params.request.db.query(model) for layer in get_layers_metadata_for_params(params, query, model): layerBodId = layer['layerBodId'] models = models_from_bodid(layerBodId, scale=scale, srid=params.srid) if models: layersDB.append({layerBodId: models}) else: gridSpec = get_grid_spec(layerBodId) if gridSpec and params.geometryType == 'esriGeometryPoint': layersGrid.append({layerBodId: gridSpec}) else: for layerBodId in params.layers: gridSpec = get_grid_spec(layerBodId) if gridSpec: if params.geometryType not in ('esriGeometryPoint', 'esriGeometryEnvelope'): raise exc.HTTPBadRequest( 'Only esriGeometryPoint or esriGeometryEnvelope' 'are supported for geometryType parameter for grid like data' ) layersGrid.append({layerBodId: gridSpec}) else: models = models_from_bodid(layerBodId, scale=scale, srid=params.srid) # The layer has a model but not at the right scale if models is not None and len(models) == 0: return response # There is no model for this layer elif models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % layerBodId) layersDB.append({layerBodId: models}) featuresGrid = _identify_grid(params, layersGrid) featuresDB = _identify_db(params, layersDB) response['results'] = featuresGrid + featuresDB return response
def _get_features(params, extended=False, process=True): ''' Returns exactly one feature or raises an excpetion ''' featureIds = params.featureIds scale = None if hasattr(params, 'imageDisplay') and hasattr(params, 'mapExtent'): if all((params.imageDisplay, params.mapExtent)): scale = get_scale(params.imageDisplay, params.mapExtent) models = models_from_bodid(params.layerId, orderScale=scale, srid=params.srid) gridSpec = get_grid_spec(params.layerId) if models is None and gridSpec is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) for featureId in featureIds: if gridSpec: bucketName = params.request.registry.settings['vector_bucket'] bucket = get_bucket(bucketName) # By convention if featureId.find('_') == -1: raise exc.HTTPBadRequest('Unexpected id formatting') col, row = featureId.split('_') grid = Grid(gridSpec.get('extent'), gridSpec.get('resolutionX'), gridSpec.get('resolutionY')) layerProperties = get_grid_layer_properties(params.layerId) timestamp = layerProperties.get('timestamp') yield _get_feature_grid(col, row, timestamp, grid, bucket, params) else: yield _get_feature_db(featureId, params, models, process=process)
def releases(request): params = _get_releases_params(request) # For this sevice, we have to use different models based # on specially sorted views. We add the _meta part to the given # layer name # Note that only zeitreihen is currently supported for this service models = models_from_bodid(params.layer + '_meta') if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layer) # Default timestamp timestamps = [] minYear = 9999 for f in _get_features_for_filters(params, [models]): if hasattr(f, 'release_year') and f.release_year is not None: for x in f.release_year: if int(x) < minYear: timestamps.append(str(x)) minYear = int(x) if len(timestamps) > 0: # remove duplicates timestamps = list(set(timestamps)) # add day to have full timestamp timestamps = sorted([int(ts + '1231') for ts in timestamps]) # transform back to string timestamps = [str(ts) for ts in timestamps] return {'results': timestamps}
def _get_features(params, extended=False, process=True): ''' Returns exactly one feature or raises an excpetion ''' featureIds = params.featureIds scale = None if hasattr(params, 'imageDisplay') and hasattr(params, 'mapExtent'): if all((params.imageDisplay, params.mapExtent)): scale = get_scale(params.imageDisplay, params.mapExtent) models = models_from_bodid(params.layerId, orderScale=scale, srid=params.srid) gridSpec = get_grid_spec(params.layerId) if models is None and gridSpec is None: raise exc.HTTPBadRequest( 'No Vector Table was found for %s' % params.layerId) for featureId in featureIds: if gridSpec: bucketName = params.request.registry.settings['vector_bucket'] bucket = get_bucket(bucketName) # By convention if featureId.find('_') == -1: raise exc.HTTPBadRequest('Unexpected id formatting') col, row = featureId.split('_') grid = Grid(gridSpec.get('extent'), gridSpec.get('resolutionX'), gridSpec.get('resolutionY')) layerProperties = get_grid_layer_properties(params.layerId) timestamp = layerProperties.get('timestamp') yield _get_feature_grid(col, row, timestamp, grid, bucket, params) else: yield _get_feature_db(featureId, params, models, process=process)
def releases(request): params = IdentifyServiceValidation(request, service='releases') # For this sevice, we have to use different models based # on specially sorted views. We add the _meta part to the given # layer name # Note that only zeitreihen is currently supported for this service # Use scale rather than resolutions for zeitreihen like the other layers resolution = get_resolution(params.imageDisplay, params.mapExtent) models = models_from_bodid(params.layerId, resolution=resolution, srid=params.srid) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) minYear = float('inf') # Default timestamp timestamps = [] # group timestamps by bgdi_order for f in _get_features_releases(models[0], params): if hasattr(f, 'array_release_years') and f.array_release_years is not None and \ hasattr(f, 'bgdi_order') and f.bgdi_order is not None: # Here we use some kind of filtering technique # to avoid returning too many results (used in service-print only) for y in f.array_release_years: if y < minYear: timestamps.append(y) minYear = y timestamps = list(set(timestamps)) # add day to have full timestamp timestamps = sorted([int(str(ts) + '1231') for ts in timestamps]) # transform back to string timestamps = [str(ts) for ts in timestamps] return {'results': timestamps}
def layerConfig(self, params): config = {} translate = params.translate settings = params.request.registry.settings wmsHost = settings['wmshost'] defaultResolution = 0.5 for k in self.__dict__.keys(): val = self.__dict__[k] if not k.startswith("_") and not k.startswith('geojsonUrl') and \ val is not None and k not in ('staging', 'srid'): if k == 'maps': config['topics'] = val elif k == 'layerBodId': config['label'] = translate(val) elif k == 'attribution': config[k] = translate(val) elif k == 'tilematrix_resolution_max': if val != defaultResolution and \ self.__dict__['srid'] != u'4326': config[ 'resolutions'] = self._getResolutionsFromMatrixSet( val, params.srid) elif k == 'extent': # Used for the shop, are still in lv03 if val and params.srid == 2056: config['extent'] = shift_to(val, 2056) else: config['extent'] = val else: config[k] = val if config['type'] in ('wmts', 'aggregate', 'geojson'): del config['singleTile'] if not config['timeEnabled']: del config['timeBehaviour'] if config['type'] == 'wms': config['wmsUrl'] = 'https://%s' % wmsHost elif config['type'] == 'geojson': api_url = params.request.registry.settings['api_url'] config['styleUrl'] = make_agnostic(api_url + '/static/vectorStyles/' + self.layerBodId + '.json') config['geojsonUrl'] = self._getGeoJsonUrl(params.lang) if 'format' in config: del config['format'] # sublayers don't have attributions if 'attribution' in config: config['attributionUrl'] = translate(self.__dict__['attribution'] + '.url') # adding __queryable_attributes__ if they have them models = models_from_bodid(self.layerBodId) if models is not None: queryable_attributes = get_models_attributes_keys( models, params.lang, True) if len(queryable_attributes) > 0: config['queryableAttributes'] = queryable_attributes return {self.layerBodId: config}
def getRandomFeatureId(self, bodId): models = models_from_bodid(bodId) with self.getSession() as session: t = session.query(models[0]).limit(500).subquery('t') query = session.query(t).order_by(func.random()).limit(1) reslt = query.one() return reslt[0]
def _get_features(params, extended=False): ''' Returns exactly one feature or raises an excpetion ''' featureIds = params.featureIds.split(',') models = models_from_bodid(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) for featureId in featureIds: # One layer can have several models for model in models: query = params.request.db.query(model) query = query.filter(model.id == featureId) try: feature = query.one() except (NoResultFound, DataError): feature = None except MultipleResultsFound: raise exc.HTTPInternalServerError('Multiple features found for the same id %s' % featureId) if feature is not None: vectorModel = model break if feature is None: raise exc.HTTPNotFound('No feature with id %s' % featureId) feature = _process_feature(feature, params) feature = {'feature': feature} yield feature, vectorModel
def _attributes(request): ''' This service exposes preview values based on a layer Id and an attribute name (mapped in the model) ''' MAX_ATTR_VALUES = 50 attributesValues = [] params = _get_attributes_params(request) models = models_from_bodid(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) # Check that the attribute provided is found at least in one model modelToQuery = None for model in models: attributes = model().getAttributesKeys() if params.attribute in attributes: modelToQuery = model break if modelToQuery is None: raise exc.HTTPBadRequest('No attribute %s was found for %s' % (params.attribute, params.layerId)) col = modelToQuery.get_column_by_property_name(params.attribute) colType = str(col.type) if colType in ['DATE', 'INTEGER', 'NUMERIC']: query = request.db.query(func.max(col).label('max'), func.min(col).label('min')) res = query.one() return {'values': [res.min, res.max]} else: query = request.db.query(col).distinct().order_by(col) query = query.limit(MAX_ATTR_VALUES) for attr in query: if len(attr): attributesValues.append(attr[0]) return {'values': sorted(attributesValues)}
def _get_features(params, extended=False): ''' Returns exactly one feature or raises an excpetion ''' featureIds = params.featureIds.split(',') models = models_from_bodid(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) for featureId in featureIds: # One layer can have several models for model in models: query = params.request.db.query(model) query = query.filter(model.id == featureId) try: feature = query.one() except (NoResultFound, DataError): feature = None except MultipleResultsFound: raise exc.HTTPInternalServerError( 'Multiple features found for the same id %s' % featureId) if feature is not None: vectorModel = model break if feature is None: raise exc.HTTPNotFound('No feature with id %s' % featureId) feature = _process_feature(feature, params) feature = {'feature': feature} yield feature, vectorModel
def layerConfig(self, params): config = {} translate = params.translate settings = params.request.registry.settings wmsHost = settings['wmshost'] defaultResolution = 0.5 for k in self.__dict__.keys(): val = self.__dict__[k] if not k.startswith("_") and not k.startswith('geojsonUrl') and \ val is not None and k not in ('staging', 'srid'): if k == 'maps': config['topics'] = val elif k == 'layerBodId': config['label'] = translate(val) elif k == 'attribution': config[k] = translate(val) elif k == 'tilematrix_resolution_max': if val != defaultResolution and \ self.__dict__['srid'] != u'4326': config['resolutions'] = self._getResolutionsFromMatrixSet( val, params.srid) elif k == 'extent': # Used for the shop, are still in lv03 if val and params.srid == 2056: config['extent'] = shift_to(val, 2056) else: config['extent'] = val else: config[k] = val if config['type'] in ('wmts', 'aggregate', 'geojson'): del config['singleTile'] if not config['timeEnabled']: del config['timeBehaviour'] if config['type'] == 'wms': config['wmsUrl'] = 'https://%s' % wmsHost elif config['type'] == 'geojson': api_url = params.request.registry.settings['api_url'] config['styleUrl'] = make_agnostic( api_url + '/static/vectorStyles/' + self.layerBodId + '.json') config['geojsonUrl'] = self._getGeoJsonUrl(params.lang) if 'format' in config: del config['format'] # sublayers don't have attributions if 'attribution' in config: config['attributionUrl'] = translate(self.__dict__['attribution'] + '.url') # adding __queryable_attributes__ if they have them models = models_from_bodid(self.layerBodId) if models is not None: queryable_attributes = get_models_attributes_keys(models, params.lang, True) if len(queryable_attributes) > 0: config['queryableAttributes'] = queryable_attributes return {self.layerBodId: config}
def _identify(request): params = IdentifyServiceValidation(request) response = {'results': []} # Determine layer types # Grid layers are serverless layersDB = [] layersGrid = [] isScaleDependent = has_buffer(params.imageDisplay, params.mapExtent, params.tolerance) scale = get_scale(params.imageDisplay, params.mapExtent) if isScaleDependent else None if params.layers == 'all': model = get_bod_model(params.lang) query = params.request.db.query(model) for layer in get_layers_metadata_for_params(params, query, model): layerBodId = layer['layerBodId'] models = models_from_bodid(layerBodId, scale=scale, srid=params.srid) if models: layersDB.append({layerBodId: models}) else: gridSpec = get_grid_spec(layerBodId) if gridSpec and params.geometryType == 'esriGeometryPoint': layersGrid.append({layerBodId: gridSpec}) else: for layerBodId in params.layers: gridSpec = get_grid_spec(layerBodId) if gridSpec: if params.geometryType not in ('esriGeometryPoint', 'esriGeometryEnvelope'): raise exc.HTTPBadRequest( 'Only esriGeometryPoint or esriGeometryEnvelope' 'are supported for geometryType parameter for grid like data') layersGrid.append({layerBodId: gridSpec}) else: models = models_from_bodid(layerBodId, scale=scale, srid=params.srid) # The layer has a model but not at the right scale if models is not None and len(models) == 0: return response # There is no model for this layer elif models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % layerBodId) layersDB.append({layerBodId: models}) featuresGrid = _identify_grid(params, layersGrid) featuresDB = _identify_db(params, layersDB) response['results'] = featuresGrid + featuresDB return response
def _identify(request): params = _get_features_params(request) if params.layers == 'all': model = get_bod_model(params.lang) query = params.request.db.query(model) layerIds = [] for layer in get_layers_metadata_for_params(params, query, model): layerIds.append(layer['layerBodId']) else: layerIds = params.layers models = [ models_from_bodid(layerId) for layerId in layerIds if models_from_bodid(layerId) is not None ] if models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % ' '.join(layerIds)) maxFeatures = 201 features = [] feature_gen = _get_features_for_filters(params, models, maxFeatures=maxFeatures, where=params.where) while True: try: feature = next(feature_gen) except InternalError as e: raise exc.HTTPBadRequest( 'Your request generated the following database error: %s' % e) except StopIteration: break else: f = _process_feature(feature, params) features.append(f) if len(features) >= maxFeatures: break return {'results': features}
def feature_attributes(request): ''' This service is used to expose the attributes of vector layers. ''' params = BaseLayersValidation(request) layerId = request.matchdict.get('layerId') models = models_from_bodid(layerId, srid=params.srid) # Models for the same layer have the same attributes if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % layerId) # Take into account all models and remove duplicated keys attributes = get_models_attributes_keys(models, params.lang, False) trackAttributesNames = [] fields = [] def insert_value_at(field, attrName, value): if field['name'] == attrName: if len(field['values']) < MAX_ATTRIBUTES_VALUES and \ value not in field['values']: field['values'].append(value) field['values'].sort() return field for model in models: query = params.request.db.query(model) query = query.limit(SAMPLE_SIZE) for rowIndex, row in enumerate(query): # attrName as defined in the model for attrIndex, attrName in enumerate(attributes): featureAttrs = row.get_attributes(exclude_pkey=False) if attrName not in trackAttributesNames and \ attrName in featureAttrs: fieldType = _find_type(model(), attrName) fields.append({ 'name': attrName, 'type': str(fieldType), 'alias': params.translate("%s.%s" % (layerId, attrName)), 'values': [] }) trackAttributesNames.append(attrName) if attrName in featureAttrs: for fieldsIndex, field in enumerate(fields): value = featureAttrs[attrName] if isinstance(value, (decimal.Decimal, datetime.date, datetime.datetime)): value = str(value) fields[fieldsIndex] = insert_value_at( field, attrName, value) return {'id': layerId, 'name': params.translate(layerId), 'fields': fields}
def _identify(request): params = _get_features_params(request) if params.layers == 'all': model = get_bod_model(params.lang) query = params.request.db.query(model) layerIds = [] for layer in get_layers_metadata_for_params(params, query, model): layerIds.append(layer['layerBodId']) else: layerIds = params.layers models = [ models_from_bodid(layerId) for layerId in layerIds if models_from_bodid(layerId) is not None ] if models is None: raise exc.HTTPBadRequest('No GeoTable was found for %s' % ' '.join(layerIds)) maxFeatures = 201 features = [] feature_gen = _get_features_for_filters(params, models, maxFeatures=maxFeatures, where=params.where) while True: try: feature = next(feature_gen) except InternalError as e: raise exc.HTTPBadRequest('Your request generated the following database error: %s' % e) except StopIteration: break else: f = _process_feature(feature, params) features.append(f) if len(features) >= maxFeatures: break return {'results': features}
def ilayersWithFeatures(self): for layer in self.ilayers(queryable=True): models = models_from_bodid(layer) assert (models is not None and len(models) > 0), layer model = models[0] query = self.session.query(model.primary_key_column()) # Depending on db size, random row is slow if self.randomFeatures: query = query.order_by(func.random()) if isinstance(self.nrOfFeatures, (int, long)): query = query.limit(self.nrOfFeatures) hasExtended = model.__extended_info__ if hasattr(model, '__extended_info__') else False for q in query: yield (layer, str(q[0]), hasExtended)
def ilayersWithFeatures(self): for layer in self.ilayers(queryable=True): models = models_from_bodid(layer) assert (models is not None and len(models) > 0), layer model = models[0] query = self.session.query(model.primary_key_column()) # Depending on db size, random row is slow if self.randomFeatures: query = query.order_by(func.random()) if isinstance(self.nrOfFeatures, (int, long)): query = query.limit(self.nrOfFeatures) hasExtended = model.__extended_info__ if hasattr( model, '__extended_info__') else False for q in query: yield (layer, str(q[0]), hasExtended)
def ilayersAllModels(self): for layer in self.ilayers(tooltip=True, geojson=False): gridSpec = get_grid_spec(layer) if gridSpec is None and layer not in self.emptyGeoTables: models = models_from_bodid(layer) assert (models is not None and len(models) > 0), layer for model in models: primaryKeyColumn = model.primary_key_column() with self.getSession() as session: query = session.query(primaryKeyColumn) query = query.limit(1) try: featureId = query.one()[0] except NoResultFound: featureId = None yield layer, featureId, model, primaryKeyColumn
def layerConfig(self, params): config = {} translate = params.translate wmsHost = params.request.registry.settings['wmshost'] for k in self.__dict__.keys(): val = self.__dict__[k] if not k.startswith("_") and not k.startswith('geojsonUrl') and \ val is not None and k not in ('staging', 'srid'): if k == 'maps': config['topics'] = val elif k == 'layerBodId': config['label'] = translate(val) elif k == 'attribution': config[k] = translate(val) elif k == 'matrixSet': if val != self.defaultMatrixSet21781 and \ self.__dict__['srid'] != '4326': config['resolutions'] = self._getResolutionsFromMatrixSet( val) else: config[k] = val layerStaging = self.__dict__['staging'] if config['type'] in ('wmts', 'aggregate', 'geojson'): del config['singleTile'] if config['type'] == 'wms': if layerStaging != 'prod': config['wmsUrl'] = make_agnostic( config['wmsUrl'].replace('wms.geo.admin.ch', wmsHost)) elif config['type'] == 'geojson': api_url = params.request.registry.settings['api_url'] config['styleUrl'] = make_agnostic( api_url + '/static/vectorStyles/' + self.layerBodId + '.json') config['geojsonUrl'] = self._getGeoJsonUrl(params.lang) # sublayers don't have attributions if 'attribution' in config: config['attributionUrl'] = translate(self.__dict__['attribution'] + '.url') # adding __queryable_attributes__ if they have them models = models_from_bodid(self.layerBodId) if models is not None: queryable_attributes = get_models_attributes_keys(models, params.lang, True) if len(queryable_attributes) > 0: config['queryableAttributes'] = queryable_attributes return {self.layerBodId: config}
def feature_attributes(request): ''' This service is used to expose the attributes of vector layers. ''' params = BaseLayersValidation(request) layerId = request.matchdict.get('layerId') models = models_from_bodid(layerId, srid=params.srid) # Models for the same layer have the same attributes if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % layerId) # Take into account all models and remove duplicated keys attributes = get_models_attributes_keys(models, params.lang, False) trackAttributesNames = [] fields = [] def insert_value_at(field, attrName, value): if field['name'] == attrName: if len(field['values']) < MAX_ATTRIBUTES_VALUES and \ value not in field['values']: field['values'].append(value) field['values'].sort() return field for model in models: query = params.request.db.query(model) query = query.limit(SAMPLE_SIZE) for rowIndex, row in enumerate(query): # attrName as defined in the model for attrIndex, attrName in enumerate(attributes): featureAttrs = row.get_attributes(exclude_pkey=False) if attrName not in trackAttributesNames and \ attrName in featureAttrs: fieldType = _find_type(model(), attrName) fields.append({'name': attrName, 'type': str(fieldType), 'alias': params.translate("%s.%s" % (layerId, attrName)), 'values': [] }) trackAttributesNames.append(attrName) if attrName in featureAttrs: for fieldsIndex, field in enumerate(fields): value = featureAttrs[attrName] if isinstance(value, (decimal.Decimal, datetime.date, datetime.datetime)): value = str(value) fields[fieldsIndex] = insert_value_at(field, attrName, value) return {'id': layerId, 'name': params.translate(layerId), 'fields': fields}
def ilayersWithFeatures(self): for layer in self.ilayers(tooltip=True, geojson=False): gridSpec = get_grid_spec(layer) if gridSpec is None and layer not in self.emptyGeoTables: models = models_from_bodid(layer) assert (models is not None and len(models) > 0), layer model = models[0] with self.getSession() as session: query = session.query(model.primary_key_column()) # Depending on db size, random row is slow if self.randomFeatures: query = query.order_by(func.random()) if isinstance(self.nrOfFeatures, (int, long)): query = query.limit(self.nrOfFeatures) hasExtended = model.__extended_info__ if hasattr(model, '__extended_info__') else False for q in query: yield (layer, str(q[0]), hasExtended)
def ilayersWithFeatures(self): for layer in self.ilayers(tooltip=True, geojson=False): gridSpec = get_grid_spec(layer) if gridSpec is None and layer not in self.emptyGeoTables: models = models_from_bodid(layer) assert (models is not None and len(models) > 0), layer model = models[0] with self.getSession() as session: query = session.query(model.primary_key_column()) # Depending on db size, random row is slow if self.randomFeatures: query = query.order_by(func.random()) if isinstance(self.nrOfFeatures, (int, long)): query = query.limit(self.nrOfFeatures) hasExtended = model.__extended_info__ if hasattr( model, '__extended_info__') else False for q in query: yield (layer, str(q[0]), hasExtended)
def checkSearch(self, layer): models = models_from_bodid(layer) assert (models is not None and len(models) > 0), layer model = models[0] expectedStatus = 200 # Special treatment for non-distributed sphinx indices (single model) if len(models) == 1: query = self.session.query(model.primary_key_column()) # we expect 404 errors for searchable layers without any data (no sphinx index) if query.first() is None: expectedStatus = 404 # If it fails here, it most probably means given layer does not have sphinx index available link = '/rest/services/all/SearchServer?features=' + layer + '&bbox=600818.7808825106,197290.49919797093,601161.2808825106,197587.99919797093&type=featuresearch&searchText=dummy' resp = self.testapp.get(link, status=expectedStatus) # If there are no features, we don't expect a sphinx index present if expectedStatus == 404: assert 'unknown local index' in resp.body
def _attributes(request): ''' This service exposes preview values based on a layer Id and an attribute name (mapped in the model) ''' MAX_ATTR_VALUES = 50 attributesValues = [] params = _get_attributes_params(request) models = models_from_bodid(params.layerId) if models is None: raise exc.HTTPBadRequest('No Vector Table was found for %s' % params.layerId) # Check that the attribute provided is found at least in one model modelToQuery = None for model in models: attributes = model().getAttributesKeys() if params.attribute in attributes: modelToQuery = model break if modelToQuery is None: raise exc.HTTPBadRequest('No attribute %s was found for %s' % (params.attribute, params.layerId)) col = modelToQuery.get_column_by_property_name(params.attribute) colType = str(col.type) if colType in ['DATE', 'INTEGER', 'NUMERIC']: query = request.db.query( func.max(col).label('max'), func.min(col).label('min')) res = query.one() return {'values': [res.min, res.max]} else: query = request.db.query(col).distinct().order_by(col) query = query.limit(MAX_ATTR_VALUES) for attr in query: if len(attr): attributesValues.append(attr[0]) return {'values': sorted(attributesValues)}