Source code for wms.layers

import mapscript

from django.db import connection
from django.conf import settings
from django.contrib.gis.db import models

try:
    from raster.fields import RasterField
except:
    RasterField = None
    pass

def to_hex(color):
    if not color[0] == '#':
        rgb = tuple(map(int, color.split(' ')))
        color = '#%02x%02x%02x' % rgb
    return color

[docs]class WmsLayer(): """ WMS Layer class representing mapserver layers. Use this class to serve data from models as WMS layers. By default, WmsLayer will use the first spatial field it finds, but the field to use can also be specified explicitly using geo_field_name. """ model = None name = None geo_field_name = None layer_name = None where = None cartography = [] classitem = None
[docs] def dispatch_by_type(self): """ Instantiates layer based on type of spatial field. Finds spatial field automatically if not set explicitly. """ # Get data type for this model field_name = self.get_spatial_field().__class__.__name__ if field_name == 'RasterField': return self.get_raster_layer() else: return self.get_vector_layer(field_name)
[docs] def get_spatial_field(self): """ Returns the spatial type for the given model based on field types. """ # Setup geo field options geo_field_options = [models.PointField, models.LineStringField, models.PolygonField, models.MultiPolygonField] if RasterField: geo_field_options += [RasterField] # If name is specified, use it, otherwise loop through candidates if self.geo_field_name: return self.model._meta.get_field_by_name(self.geo_field_name) else: for field in self.model._meta.concrete_fields: if any([issubclass(field.__class__, geofield) for geofield in geo_field_options]): return field # Raise error if no spatial field match was found raise TypeError('No spatial field match found in specified model. '\ 'Specify a model that has a spatial field')
[docs] def get_name(self): """ Returns WMS layer name, defaults to model name if not provided. """ if self.name: return self.name else: return self.model._meta.model_name
[docs] def get_srs(self): """ Returns srs for this layer based on field specification. """ instance = self.model.objects.first() if hasattr(instance, 'rasterlayer'): return str(instance.rasterlayer.srid) else: return str(self.get_spatial_field().srid)
[docs] def get_base_layer(self): """ Instantiates and returns a base WMS layer with attributes that are not specific to data types. """ # Instanciate mapscript layer layer = mapscript.layerObj() layer.status = mapscript.MS_OFF layer.name = self.get_name() layer.setProjection('init=epsg:' + self.get_srs()) layer.metadata.set('wms_title', 'Landcover') layer.opacity = 80 # Allow debugging if settings.DEBUG: layer.debug = mapscript.MS_ON return layer
[docs] def get_vector_layer(self, field_name): """ Connect this layer to a vector data model. """ # Get base layer layer = self.get_base_layer() # Specify input data type layer_types = { 'PointField': mapscript.MS_LAYER_POINT, 'LineStringField': mapscript.MS_LAYER_LINE, 'PolygonField': mapscript.MS_LAYER_POLYGON, 'MultiPolygonField': mapscript.MS_LAYER_POLYGON } layer.type = layer_types[field_name] # Set connection to DB layer.setConnectionType(mapscript.MS_POSTGIS, '') layer.connection = 'host={host} dbname={dbname} user={user} '\ 'port={port} password={password}'.format( host=settings.DATABASES['default']['HOST'], dbname=settings.DATABASES['default']['NAME'], user=settings.DATABASES['default']['USER'], port=settings.DATABASES['default']['PORT'], password=settings.DATABASES['default']['PASSWORD'] ) # Select data column layer.data = 'geom FROM {0}'.format(self.model._meta.db_table) # Set class item if self.classitem: layer.classitem = self.classitem # Cartography settings if self.cartography: for cart in self.cartography: # Set categorization and name category = mapscript.classObj(layer) category.setExpression(cart.get('expression', '')) category.name = cart.get('name', cart.get('expression','')) # Set category style style = mapscript.styleObj(category) style.color.setHex(to_hex(cart.get('color', '#777777'))) style.outlinecolor.setHex(to_hex(cart.get('outlinecolor', '#000000'))) style.width = cart.get('width', 1) # Set symbol name now, this will be linked to the map level # symbolset when registering layers in map. if cart.has_key('symbol'): style.symbolname = cart.get('symbol') else: category = mapscript.classObj(layer) category.name = layer.name style = mapscript.styleObj(category) style.color.setHex('#777777') style.outlinecolor.setHex('#000000') style.width = 1 return layer
[docs] def get_raster_layer(self): """ Connect this layer to a raster model. """ # Get base layer and specify type layer = self.get_base_layer() layer.type = mapscript.MS_LAYER_RASTER # Set class item if self.classitem: layer.classitem = self.classitem else: layer.classitem="[pixel]" # Set data source layer.data = "PG:host='{host}' dbname='{dbname}' user='{user}' "\ "port='{port}' password='{password}' mode=2 ".format( host=settings.DATABASES['default']['HOST'], dbname=settings.DATABASES['default']['NAME'], user=settings.DATABASES['default']['USER'], port=settings.DATABASES['default']['PORT'], password=settings.DATABASES['default']['PASSWORD'] ) layer.data += "table='" + self.model._meta.db_table + "'" # Set where clause if provided if self.where: layer.data += " where='" + self.where + "'" # Set nodata if provided if self.nodata: layer.addProcessing("NODATA=" + self.nodata) # Class and style settings if self.cartography: for cart in self.cartography: # Set categorization category = mapscript.classObj(layer) category.setExpression(cart['expression']) category.name = cart['name'] # Set category style style = mapscript.styleObj(category) style.color.setHex(to_hex(cart['color'])) else: category = mapscript.classObj(layer) category.name = self.get_layer_name() style = mapscript.styleObj(category) style.color.setHex('#FF00FF') return layer

Table Of Contents