/django/contrib/gis/admin/widgets.py
Python | 107 lines | 95 code | 3 blank | 9 comment | 1 complexity | 9147a3b996f842ee2df64d13ba0d376f MD5 | raw file
1from django.conf import settings 2from django.contrib.gis.gdal import OGRException 3from django.contrib.gis.geos import GEOSGeometry, GEOSException 4from django.forms.widgets import Textarea 5from django.template import loader, Context 6from django.utils import translation 7 8# Creating a template context that contains Django settings 9# values needed by admin map templates. 10geo_context = Context({'ADMIN_MEDIA_PREFIX' : settings.ADMIN_MEDIA_PREFIX, 11 'LANGUAGE_BIDI' : translation.get_language_bidi(), 12 }) 13 14class OpenLayersWidget(Textarea): 15 """ 16 Renders an OpenLayers map using the WKT of the geometry. 17 """ 18 def render(self, name, value, attrs=None): 19 # Update the template parameters with any attributes passed in. 20 if attrs: self.params.update(attrs) 21 22 # Defaulting the WKT value to a blank string -- this 23 # will be tested in the JavaScript and the appropriate 24 # interface will be constructed. 25 self.params['wkt'] = '' 26 27 # If a string reaches here (via a validation error on another 28 # field) then just reconstruct the Geometry. 29 if isinstance(value, basestring): 30 try: 31 value = GEOSGeometry(value) 32 except (GEOSException, ValueError): 33 value = None 34 35 if value and value.geom_type.upper() != self.geom_type: 36 value = None 37 38 # Constructing the dictionary of the map options. 39 self.params['map_options'] = self.map_options() 40 41 # Constructing the JavaScript module name using the name of 42 # the GeometryField (passed in via the `attrs` keyword). 43 # Use the 'name' attr for the field name (rather than 'field') 44 self.params['name'] = name 45 # note: we must switch out dashes for underscores since js 46 # functions are created using the module variable 47 js_safe_name = self.params['name'].replace('-','_') 48 self.params['module'] = 'geodjango_%s' % js_safe_name 49 50 if value: 51 # Transforming the geometry to the projection used on the 52 # OpenLayers map. 53 srid = self.params['srid'] 54 if value.srid != srid: 55 try: 56 ogr = value.ogr 57 ogr.transform(srid) 58 wkt = ogr.wkt 59 except OGRException: 60 wkt = '' 61 else: 62 wkt = value.wkt 63 64 # Setting the parameter WKT with that of the transformed 65 # geometry. 66 self.params['wkt'] = wkt 67 68 return loader.render_to_string(self.template, self.params, 69 context_instance=geo_context) 70 71 def map_options(self): 72 "Builds the map options hash for the OpenLayers template." 73 74 # JavaScript construction utilities for the Bounds and Projection. 75 def ol_bounds(extent): 76 return 'new OpenLayers.Bounds(%s)' % str(extent) 77 def ol_projection(srid): 78 return 'new OpenLayers.Projection("EPSG:%s")' % srid 79 80 # An array of the parameter name, the name of their OpenLayers 81 # counterpart, and the type of variable they are. 82 map_types = [('srid', 'projection', 'srid'), 83 ('display_srid', 'displayProjection', 'srid'), 84 ('units', 'units', str), 85 ('max_resolution', 'maxResolution', float), 86 ('max_extent', 'maxExtent', 'bounds'), 87 ('num_zoom', 'numZoomLevels', int), 88 ('max_zoom', 'maxZoomLevels', int), 89 ('min_zoom', 'minZoomLevel', int), 90 ] 91 92 # Building the map options hash. 93 map_options = {} 94 for param_name, js_name, option_type in map_types: 95 if self.params.get(param_name, False): 96 if option_type == 'srid': 97 value = ol_projection(self.params[param_name]) 98 elif option_type == 'bounds': 99 value = ol_bounds(self.params[param_name]) 100 elif option_type in (float, int): 101 value = self.params[param_name] 102 elif option_type in (str,): 103 value = '"%s"' % self.params[param_name] 104 else: 105 raise TypeError 106 map_options[js_name] = value 107 return map_options